Skip to content

Bug: IcaoDecoder.isMilitary silently returns false for non-hex or over-length ICAO addresses (no input validation) #538

Open

Description

@kevinelliott

Summary

IcaoDecoder.isMilitary (lib/IcaoDecoder.ts:46-55) calls parseInt(this.icao, 16) without validating that the input is exactly 6 hex digits (a 24-bit Mode-S address). Non-hex or overly long strings both silently produce false, obscuring real failures and corrupting results.

Failures

Non-hex input — new IcaoDecoder('zzzzzz').isMilitary():

  • parseInt('zzzzzz', 16) → NaN
  • Every start <= NaN && NaN <= end is false
  • Returns false as if the aircraft were confirmed civilian.

Over-length input — new IcaoDecoder('3B70000ff').isMilitary():

  • parseInt('3B70000ff', 16) → 0x3B70000ff = 15,956,738,815, way outside the 24-bit space
  • No range matches, returns false
  • The real 24-bit prefix 0x3B7000 is in the France 2 military range [0x3b7000, 0x3bffff], so the correct answer for the intended ICAO is true.

parseInt tolerates stray prefix suffix characters:

  • parseInt('3B7000 ', 16) works (trailing space OK), but parseInt('_3B7000', 16) → NaN
  • parseInt('0x3B7000', 16) → 0x3B7000 — the 0x prefix is accepted here, which may or may not be intended.

Impact

Callers that log, display, or filter on isMilitary() can't distinguish "known civilian" from "I couldn't parse your input". Any upstream data cleanliness issue (whitespace, extra characters, placeholder like ------) silently flips to a false answer.

Fix sketch

isMilitary(): boolean {
  if (!/^[0-9a-fA-F]{6}$/.test(this.icao)) {
    return false; // or throw / return null — pick one and document it
  }
  const n = parseInt(this.icao, 16);
  for (const [start, end] of IcaoDecoder.MILITARY_RANGES) {
    if (start <= n && n <= end) return true;
  }
  return false;
}

Preferably widen the return type (boolean | null or add an isValid()) so callers can tell "valid, civilian" apart from "unparseable".

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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