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: