diff --git a/CHANGELOG.md b/CHANGELOG.md index da9a440..b1006a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,10 +25,10 @@ will not match the sender it came from. Ids most SMSCs issue are digits or hex and are unaffected. - A `U+0000` inside a C-Octet String — `source_addr`, `message_id`, `system_id` and the rest — is refused. An Octet String carries a NULL as before. -- A number with no decimal spelling — `NaN`, `Infinity`, `-Infinity` — is refused where a text field - takes one. `sendSms({ from: NaN })` put the literal sender `NaN` on the wire and reported the send - as successful; `message_id`, `source_addr` and every other text field took such a number the same - way. A finite number still writes its decimals, so `message_id: 123` is unchanged. +- A non-finite number — `NaN`, `Infinity`, `-Infinity` — is refused where a text field takes one. + `sendSms({ from: NaN })` put the literal sender `NaN` on the wire and reported the send as + successful; `message_id`, `source_addr` and every other text field took such a number the same way. + Any other number goes out as `String()` spells it, so `message_id: 123` is unchanged. ## 0.5.0 diff --git a/test/pdu.test.ts b/test/pdu.test.ts index e4563dc..cab91b7 100644 --- a/test/pdu.test.ts +++ b/test/pdu.test.ts @@ -51,6 +51,11 @@ describe('header', () => { assert.equal(decode(encode({ cmdName: 'enquire_link', seqNr: 0x80000001 })).seqNr, 0x80000001); assert.equal(decode(encode({ cmdName: 'enquire_link', seqNr: 0xFFFFFFFF })).seqNr, 0xFFFFFFFF); assert.ok(objToPdu({ cmdName: 'submit_sm', seqNr: 0x100000000 }).err instanceof Error); + + const notANumber = objToPdu({ cmdName: 'submit_sm', seqNr: NaN }); + + assert.ok(notANumber.err instanceof Error); + assert.match(notANumber.err.message, /NaN/); }); }); @@ -144,7 +149,7 @@ describe('parsing real PDUs', () => { assert.equal(decode(pdu).params.source_addr, 'Kaffeé'); }); - test('refuses an address the field cannot carry rather than truncating it', () => { + test('refuses an address the field cannot carry rather than truncating or coercing it', () => { const smuggled = objToPdu({ cmdName: 'submit_sm', params: { destination_addr: '46709771337', source_addr: '46701113311\u0000EVIL' }, @@ -154,7 +159,6 @@ describe('parsing real PDUs', () => { assert.equal(smuggled.buffer, undefined); assert.ok(objToPdu({ cmdName: 'deliver_sm', params: { source_addr: '一' } }).err instanceof Error); - // Coercing these spells the senders "NaN" and "Infinity", which a peer reads as those letters. assert.ok(objToPdu({ cmdName: 'deliver_sm', params: { source_addr: NaN } }).err instanceof Error); assert.ok(objToPdu({ cmdName: 'deliver_sm', params: { source_addr: Infinity } }).err instanceof Error); }); diff --git a/test/types.test.ts b/test/types.test.ts index 51ddc51..c55cc86 100644 --- a/test/types.test.ts +++ b/test/types.test.ts @@ -39,6 +39,12 @@ describe('integers', () => { assert.ok(types.int8.write(-1, Buffer.alloc(1), 0).err instanceof Error); assert.ok(types.int16.write(1.5, Buffer.alloc(2), 0).err instanceof Error); assert.ok(types.int8.write('nope', Buffer.alloc(1), 0).err instanceof Error); + + const notANumber = types.int8.write(NaN, Buffer.alloc(1), 0); + + // JSON spells NaN and the infinities `null`, which is a value the caller never wrote. + assert.ok(notANumber.err instanceof Error); + assert.match(notANumber.err.message, /NaN/); }); }); @@ -112,7 +118,7 @@ describe('cstring (C-Octet String)', () => { assert.deepEqual(target, encoded); }); - test('coerces a numeric value to its decimal string, and refuses one with no decimals', () => { + test('coerces a numeric value to its decimal string, and refuses a non-finite one', () => { const target = Buffer.alloc(4); types.cstring.write(123, target, 0); @@ -124,7 +130,9 @@ describe('cstring (C-Octet String)', () => { assert.ok(types.cstring.size(value).err instanceof Error, String(value)); assert.ok(types.cstring.write(value, Buffer.alloc(9), 0).err instanceof Error, String(value)); assert.ok(types.string.write(value, Buffer.alloc(9), 0).err instanceof Error, String(value)); + assert.ok(types.buffer.write(value, Buffer.alloc(9), 0).err instanceof Error, String(value)); assert.ok(types.tlv.string.write(value, Buffer.alloc(9), 0).err instanceof Error, String(value)); + assert.ok(types.tlv.cstring.write(value, Buffer.alloc(9), 0).err instanceof Error, String(value)); } });