diff --git a/CHANGELOG.md b/CHANGELOG.md index 607bd46..d64159f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,8 @@ other limits. `server({ maxOctets: 0 })` used to start and then refuse every multipart message. - `callback_num`, `callback_num_atag`, `callback_num_pres_ind`, `broadcast_area_identifier` and `broadcast_error_status` read as a list of every copy the peer sent, where only the last was kept, - and are written from a list. A single value for one of them, or a list for any other tag, is + and are written from a list. A single value or an empty list for one of them, or a list for any + other tag, is refused. - `tlvMap` is gone from the `broadcast_sm_resp` command definition. Nothing read it. diff --git a/src/defs/tlvs.ts b/src/defs/tlvs.ts index fd789cf..de7ac07 100644 --- a/src/defs/tlvs.ts +++ b/src/defs/tlvs.ts @@ -135,7 +135,11 @@ export function tagIdOf(name: string, input: TlvInput): Result<{ tagId: number } function copiesOf(name: string, definition: TlvDefinition | undefined, value: TlvValue): Result<{ copies: TlvScalar[] }> { const multiple = definition?.multiple === true; - if (Array.isArray(value) && multiple) return { copies: value }; + if (Array.isArray(value) && multiple) { + return value.length > 0 + ? { copies: value } + : { err: new Error(`TLV "${name}": give at least one value, or leave the tag out`) }; + } if (!Array.isArray(value) && !multiple) return { copies: [value] }; diff --git a/test/pdu.test.ts b/test/pdu.test.ts index 3046978..459b7c9 100644 --- a/test/pdu.test.ts +++ b/test/pdu.test.ts @@ -432,16 +432,18 @@ describe('TLVs', () => { assert.deepEqual(pduObj.tlvs.callback_num_pres_ind?.tagValue, [1]); }); - test('refuses a single value for a tag SMPP lets repeat, and a list for one it does not', () => { + test('refuses a single value or an empty list for a tag SMPP lets repeat, and a list for one it does not', () => { const params = { destination_addr: '46709771337', short_message: 'hi', source_addr: '46701113311' }; const single = objToPdu({ cmdName: 'submit_sm', params, tlvs: { callback_num: { tagValue: Buffer.from('46701113311', 'latin1') } }, }); + const empty = objToPdu({ cmdName: 'submit_sm', params, tlvs: { callback_num: { tagValue: [] } } }); const list = objToPdu({ cmdName: 'submit_sm', params, tlvs: { source_port: { tagValue: [1234] } } }); assert.match(single.err?.message ?? '', /TLV "callback_num": .*list/); + assert.match(empty.err?.message ?? '', /TLV "callback_num": .*leave the tag out/); assert.match(list.err?.message ?? '', /TLV "source_port": .*list/); });