On Tue, Apr 21, 2026 at 09:23:03AM +0200, [email protected] wrote: > expand_domacro() in libexec/tradcpp/macro.c handles a defined() > with the wrong argument count via an error path that doesn't > drain es->args: > > if (stringarray_num(&es->args) != 1) { > complain(p, "Too many arguments for defined()"); > complain_fail(); > expand_send(es, p, "0", 1); > return; > } > name = stringarray_get(&es->args, 0); > m = macrotable_find(name, false); > val = (m != NULL) ? "1" : "0"; > debuglog(p, "defined(%s): %s", name, val); > expand_send(es, p, val, 1); > expstate_destroyargs(es); > return; > > The success path calls expstate_destroyargs(es) before returning; > the error path does not. es->args stays populated. On shutdown > array_cleanup() in libexec/tradcpp/array.c asserts a->num == 0 > and tradcpp aborts with SIGABRT. > > Minimum reproducer (17 bytes): > > echo '#if defined(a,b)' | tradcpp /dev/stdin > > Output: > > <stdin>:1:5: Too many arguments for defined() > assertion "a->num == 0" failed: file "array.c", line 63, > function "array_cleanup" > Abort trap > > Reproduced on OpenBSD 7.9 arm64, amd64 and i386 with plain cc > (no sanitizers). Found by AFL++ fuzzing. > > OK?
ok jsg@ > > Index: libexec/tradcpp/macro.c > =================================================================== > RCS file: /cvs/src/libexec/tradcpp/macro.c,v > retrieving revision 1.4 > diff -u -p -r1.4 macro.c > --- libexec/tradcpp/macro.c 23 Aug 2019 04:38:55 -0000 1.4 > +++ libexec/tradcpp/macro.c > @@ -885,6 +885,7 @@ expand_domacro(struct expstate *es, stru > complain(p, "Too many arguments for defined()"); > complain_fail(); > expand_send(es, p, "0", 1); > + expstate_destroyargs(es); > return; > } > name = stringarray_get(&es->args, 0); > >
