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?
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);
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.