Skip to content

Bug: Label_ColonComma unconditionally returns decoded:true / decodeLevel:'full' for any input, even non-numeric text — emits NaN frequency silently #483

Description

@kevinelliott

Summary

Label_ColonComma.decode calls Number(message.text) / 1000, pushes the value into formatted.items, and sets decoded = true / decodeLevel = 'full' — with no validation whatsoever. For any non-numeric or empty payload, Number(...) returns NaN, and the plugin reports a "fully decoded" Aircraft Transceiver Frequency Change result with raw.frequency = NaN and the string "NaN MHz" in the formatted output.

Same false-success pattern as #463 (Label_8E) and #476 (Label_H2_02E), but for a different plugin.

Affected code

lib/plugins/Label_ColonComma.ts:14-32

decode(message: Message, options: Options = {}): DecodeResult {
  const decodeResult = this.defaultResult();
  decodeResult.decoder.name = this.name;

  decodeResult.raw.frequency = Number(message.text) / 1000;      // ← NaN on non-numeric text

  decodeResult.formatted.description =
    'Aircraft Transceiver Frequency Change';
  decodeResult.formatted.items.push({
    type: 'frequency',
    label: 'Frequency',
    value: `${decodeResult.raw.frequency} MHz`,                  // ← "NaN MHz"
    code: 'FREQ',
  });

  decodeResult.decoded = true;                                    // ← unconditional
  decodeResult.decoder.decodeLevel = 'full';                      // ← unconditional
  return decodeResult;
}

Also note: the plugin registers labels: [':;'] (colon-semicolon), but its class name is Label_ColonComma — a naming inconsistency that's worth cleaning up alongside the fix, though the label itself matches what MessageDecoder dispatches on.

Reproduction

const decoder = new MessageDecoder();

const r = decoder.decode({ label: ':;', text: 'not-a-number' });
// r.decoded === true
// r.decoder.decodeLevel === 'full'
// r.raw.frequency === NaN
// r.formatted.items[0].value === 'NaN MHz'

const r2 = decoder.decode({ label: ':;', text: '' });
// r2.decoded === true, r2.raw.frequency === 0, r2.formatted.items[0].value === '0 MHz'

The existing tests in lib/plugins/Label_ColonComma.test.ts only cover valid numeric inputs (131550, 129125).

Suggested fix

Validate the input before formatting, matching the #463 suggested pattern:

const kHz = Number(message.text);
if (!Number.isFinite(kHz) || message.text.trim().length === 0) {
  ResultFormatter.unknown(decodeResult, message.text);
  decodeResult.decoded = false;
  decodeResult.decoder.decodeLevel = 'none';
  return decodeResult;
}
decodeResult.raw.frequency = kHz / 1000;
// ... push formatted item ...
decodeResult.decoded = true;
decodeResult.decoder.decodeLevel = 'full';

Test coverage

Add cases to Label_ColonComma.test.ts:

  • text: 'not-a-number'decoded: false, decodeLevel: 'none'
  • text: ''decoded: false, decodeLevel: 'none'

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions