Thanks, I'll get on this later!
--
Dave Hibberd <[email protected]>
Debian Developer
Packet Radioist
MM0RFN
On Tue, 11 Aug 2026, at 11:04 PM, ch wrote:
> Package: nec2c
> Version: 1.3.1-3
> Severity: important
> Tags: upstream security
>
> main() reads deck lines into an 81-byte buffer, while load_line() fills a
> caller's buffer with up to LINE_LEN (132) characters plus a terminator:
>
> main.c:41 char ain[3], line_buf[81];
> nec2c.h:81 #define LINE_LEN 132
> misc.c while( num_chr < LINE_LEN ) { buff[num_chr++] = (char)chr; ... }
> buff[num_chr] = '\0';
>
> A card line longer than 81 characters therefore overflows line_buf by up to 52
> bytes. A NEC-2 comment card is 80 columns plus its "CM ", so ordinary input
> reaches it; no malformed or hostile deck is required.
>
> Reproducer -- a deck whose second CM card is 100 characters. It must not be
> the first line, which is read on a different path:
>
> {
> echo "CM first"
> echo "CM $(printf 'A%.0s' {1..100})"
> echo "CE"
> echo "GW 1 9 0 0 0 0 0 1 0.001"
> echo "GE 0"
> echo "EK"
> echo "EX 0 1 5 0 1.0 0.0"
> echo "FR 0 1 0 0 145.9 0"
> echo "RP 0 3 1 1000 0 0 30 0"
> echo "EN"
> } > t.nec
> nec2c -i t.nec -o t.out
>
> Built from the 1.3.1-3 source with gcc -O0 -g -fsanitize=address:
>
> ERROR: AddressSanitizer: stack-buffer-overflow
> WRITE of size 1
> #0 load_line misc.c:154
> #1 main main.c:269
> [1920, 2001) 'line_buf' (line 41) <== Memory access at offset 2001
> overflows this variable
>
> The packaged binary usually does not crash, because main()'s infile[81] and
> otfile[81] are adjacent to line_buf and absorb the overrun rather than the
> stack canary. That makes it quiet, not harmless: it is an out-of-bounds write
> whose length is controlled by the input file.
>
> Severity: this is a local command-line tool reading a file the user chose, so
> I have not filed it as a security issue. It would deserve one for any workflow
> that feeds it decks from an untrusted source.
>
> Upstream status: upstream git (https://github.com/KJ7LNW/nec2c) widened the
> buffer to LINE_LEN in 3d8c230, before tagging v1.3.1. That reduces the
> overflow to a single byte but does not remove it -- load_line() still writes
> buff[LINE_LEN] into a char[LINE_LEN] -- and I have reported that separately.
> There is therefore no released upstream version to upgrade to yet.
>
> Suggested fix, which is sufficient on its own against the 1.3.1-3 source:
>
> --- a/main.c
> +++ b/main.c
> @@
> - char ain[3], line_buf[81];
> + char ain[3], line_buf[LINE_LEN+1];
>
> With that applied, ASan is clean on the reproducer and an over-long line is
> rejected rather than corrupting memory.