Summary
lib/plugins/Label_83.ts variant-2 handler activates whenever text.startsWith('4DH3 ETAT2'). It then splits on whitespace and immediately reads fields[2].length, fields[3].split('/'), fields[4].replace(...), and fields[6] + '00' — none of which are guarded by a length check. Any short-form or truncated 4DH3 ETAT2… input throws TypeError at line 31. Because MessageDecoder.decode() does not wrap plugin calls in try/catch, the exception aborts the entire decode call for that message.
Location
lib/plugins/Label_83.ts:28-42
if (text.startsWith('4DH3 ETAT2')) {
// variant 2
const fields = text.split(WS_REGEX);
if (fields[2].length > 5) { // <-- throws when fields.length <= 2
decodeResult.raw.day = fields[2].substring(5);
}
ResultFormatter.unknown(decodeResult, fields[2].substring(0, 4));
const subfields = fields[3].split('/'); // <-- throws if fields.length <= 3
ResultFormatter.departureAirport(decodeResult, subfields[0]);
ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
ResultFormatter.tail(decodeResult, fields[4].replace(ALL_DOTS_REGEX, ''));
ResultFormatter.eta(
decodeResult,
DateTimeUtils.convertHHMMSSToTod(fields[6] + '00'), // <-- undefined + '00' → NaN downstream
);
}
Reproduction
const decoder = new MessageDecoder();
decoder.decode({ label: '83', text: '4DH3 ETAT2' });
// Uncaught TypeError: Cannot read properties of undefined (reading 'length')
// at Label_83.decode (Label_83.ts:31)
// at MessageDecoder.decode (MessageDecoder.ts:198)
'4DH3 ETAT2'.split(/\s+/) produces ['4DH3', 'ETAT2'] (length 2), so fields[2] is undefined and fields[2].length throws. Real-world truncation of the airline preamble message (or a variant with a slightly different but still 4DH3 ETAT2-prefixed header) exposes this.
Expected
For any input starting with 4DH3 ETAT2 but shorter than the fully-fleshed variant-2 form, the plugin should either return decoded: false or gracefully degrade — it should not throw.
Actual
Uncaught TypeError propagates out of MessageDecoder.decode(), aborting the decode call entirely. Later plugins in the candidates list are never tried, and the caller receives a thrown error rather than a normal DecodeResult.
Recommendation
Add an early length guard at the top of the variant-2 branch:
if (text.startsWith('4DH3 ETAT2')) {
const fields = text.split(WS_REGEX);
if (fields.length < 7) {
decodeResult.decoded = false;
ResultFormatter.unknown(decodeResult, text);
} else {
// existing decode …
}
}
Consider also hardening MessageDecoder.decode() to catch plugin exceptions so a single buggy plugin cannot take down the whole decoder for a message — but the primary fix belongs in this plugin.
Notes
- The existing test only covers the fully-fleshed happy-path input
'4DH3 ETAT2 0907/22 ENGM/KEWR .LN-RKO\r\n/ETA 1641'. No truncation test.
Label_83 has no preambles in its qualifiers, so this branch is reached whenever the startsWith succeeds — even if surrounding routing changes.
Summary
lib/plugins/Label_83.tsvariant-2 handler activates whenevertext.startsWith('4DH3 ETAT2'). It then splits on whitespace and immediately readsfields[2].length,fields[3].split('/'),fields[4].replace(...), andfields[6] + '00'— none of which are guarded by a length check. Any short-form or truncated4DH3 ETAT2…input throwsTypeErrorat line 31. BecauseMessageDecoder.decode()does not wrap plugin calls intry/catch, the exception aborts the entire decode call for that message.Location
lib/plugins/Label_83.ts:28-42Reproduction
'4DH3 ETAT2'.split(/\s+/)produces['4DH3', 'ETAT2'](length 2), sofields[2]isundefinedandfields[2].lengththrows. Real-world truncation of the airline preamble message (or a variant with a slightly different but still4DH3 ETAT2-prefixed header) exposes this.Expected
For any input starting with
4DH3 ETAT2but shorter than the fully-fleshed variant-2 form, the plugin should either returndecoded: falseor gracefully degrade — it should not throw.Actual
Uncaught
TypeErrorpropagates out ofMessageDecoder.decode(), aborting the decode call entirely. Later plugins in the candidates list are never tried, and the caller receives a thrown error rather than a normalDecodeResult.Recommendation
Add an early length guard at the top of the variant-2 branch:
Consider also hardening
MessageDecoder.decode()to catch plugin exceptions so a single buggy plugin cannot take down the whole decoder for a message — but the primary fix belongs in this plugin.Notes
'4DH3 ETAT2 0907/22 ENGM/KEWR .LN-RKO\r\n/ETA 1641'. No truncation test.Label_83has nopreamblesin its qualifiers, so this branch is reached whenever thestartsWithsucceeds — even if surrounding routing changes.