ok Otto Moerbeek(o...@drijf.net) on 2015.11.20 14:22:12 +0100: > On Fri, Nov 20, 2015 at 11:52:16AM +0100, Otto Moerbeek wrote: > > > On Thu, Nov 19, 2015 at 05:52:39PM -0500, Michael McConville wrote: > > > > > I'm already cache-thrashing with all of my side projects, so if anyone's > > > interested I'll leave this to them. > > > > > > A few days ago, I wanted to try American Fuzzy Lop (afl), and bc(1) > > > seemed like a good first target: it pretty much just goes from stdin to > > > stdout, so there's no code reorganization needed. > > > > > > For those not familiar, bc compiles its input to dc(1)'s syntax and > > > forks to dc. > > > > > > There are many unique crash paths - 1041 before I killed afl. Most > > > center around emit(), which emits a dc instr. Many pass NULL to fputs() > > > in emit(). I found at least one (crashes/id:001041*) that > > > nondeterministically passes the str pointer 0xdfdfdfdfdfdfdfdf to > > > fputs(), which is probably uninitialized or already-freed memory. > > > Backtrace below. > > > > > > malloc.conf(5) may be useful. > > > > > > Here's the full afl directory: > > > > > > http://www.sccs.swarthmore.edu/users/16/mmcconv1/bc-afl/ > > > > > > > > > Core was generated by `bc'. > > > Program terminated with signal SIGBUS, Bus error. > > > #0 strlen () at /usr/src/lib/libc/arch/amd64/string/strlen.S:152 > > > 152 movq (%rax),%rdx /* first data in high > > > bytes */ > > > (gdb) bt > > > #0 strlen () at /usr/src/lib/libc/arch/amd64/string/strlen.S:152 > > > #1 0x000019f79fa7c43d in *_libc_fputs (s=0xdfdfdfdfdfdfdfdf <error: > > > Cannot access memory at address 0xdfdfdfdfdfdfdfdf>, fp=0x1) at > > > /usr/src/lib/libc/stdio/fputs.c:50 > > > #2 0x000019f4ecb0f401 in emit (i=28548786530304) at > > > /usr/src/usr.bin/bc/bc.y:810 > > > #3 yyparse () at /usr/src/usr.bin/bc/bc.y:178 > > > #4 0x000019f4ecb13f3e in main (argc=1, argv=0x7f7fffffa570) at > > > /usr/src/usr.bin/bc/bc.y:1188 > > > > This fixes at least one case (id-000141*) and make the printing of > > non-ascci chars better > > > > -Otto > > > > New version, which solves all cases found in crashes, hangs and queue > above. The remaining cases were emit going into an infinite recursion > becuse the tree wasn't a tree but a cyclic graph. > > Regress still succeeds. > > -Otto > > Index: bc.y > =================================================================== > RCS file: /cvs/src/usr.bin/bc/bc.y,v > retrieving revision 1.48 > diff -u -p -r1.48 bc.y > --- bc.y 10 Oct 2015 19:28:54 -0000 1.48 > +++ bc.y 20 Nov 2015 13:19:07 -0000 > @@ -72,7 +72,7 @@ static void grow(void); > static ssize_t cs(const char *); > static ssize_t as(const char *); > static ssize_t node(ssize_t, ...); > -static void emit(ssize_t); > +static void emit(ssize_t, int); > static void emit_macro(int, ssize_t); > static void free_tree(void); > static ssize_t numnode(int); > @@ -175,7 +175,7 @@ program : /* empty */ > > input_item : semicolon_list NEWLINE > { > - emit($1); > + emit($1, 0); > macro_char = reset_macro_char; > putchar('\n'); > free_tree(); > @@ -803,12 +803,17 @@ node(ssize_t arg, ...) > } > > static void > -emit(ssize_t i) > +emit(ssize_t i, int level) > { > - if (instructions[i].index >= 0) > - while (instructions[i].index != END_NODE) > - emit(instructions[i++].index); > - else > + if (level > 1000) > + errx(1, "internal error: tree level > 1000"); > + if (instructions[i].index >= 0) { > + while (instructions[i].index != END_NODE && > + instructions[i].index != i) { > + emit(instructions[i].index, level + 1); > + i++; > + } > + } else if (instructions[i].index != END_NODE) > fputs(instructions[i].u.cstr, stdout); > } > > @@ -816,7 +821,7 @@ static void > emit_macro(int node, ssize_t code) > { > putchar('['); > - emit(code); > + emit(code, 0); > printf("]s%s\n", instructions[node].u.cstr); > nesting--; > } > @@ -951,7 +956,7 @@ yyerror(char *s) > !isprint((unsigned char)yytext[0])) > n = asprintf(&str, > "%s: %s:%d: %s: ascii char 0x%02x unexpected", > - __progname, filename, lineno, s, yytext[0]); > + __progname, filename, lineno, s, yytext[0] & 0xff); > else > n = asprintf(&str, "%s: %s:%d: %s: %s unexpected", > __progname, filename, lineno, s, yytext); >
--