From e7e1ce352703729db39a756146df329f0cc69a57 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Tue, 18 Aug 2026 14:47:02 -0500 Subject: [PATCH] grep -B wasn't handling NUL bytes properly, reported by arbruijn on codeberg. --- tests/grep.test | 3 ++- toys/posix/grep.c | 37 +++++++++++++++++-------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/tests/grep.test b/tests/grep.test index be2414aa..c1aa51ca 100755 --- a/tests/grep.test +++ b/tests/grep.test @@ -157,9 +157,10 @@ testcmd "-l overrides -C" "-l -C1 two test input" "test\ninput\n" \ "three\ntwo\none\n" "" rm test -# match after NUL byte testcmd "match after NUL byte" "-a two" "one\0and two three\n" \ "" 'one\0and two three' +testcmd "NUL in -B" "-B2 X" "A\0BBBBBB\xff\xff\xff\x7f\nX\n" \ + "" 'A\0BBBBBB\xff\xff\xff\x7f\nX\n' # BREs versus EREs testcmd "implicit BRE |" "'uno|dos'" "uno|dos\n" "" "uno\ndos\nuno|dos\n" diff --git a/toys/posix/grep.c b/toys/posix/grep.c index d1ccbaed..34840480 100644 --- a/toys/posix/grep.c +++ b/toys/posix/grep.c @@ -78,6 +78,12 @@ struct reg { regmatch_t m; }; +struct dlb { + struct dlb *next, *prev; + unsigned bcount, trim; + char data[]; +}; + static void numdash(long num, char dash) { printf("%s%ld%s%c", TT.green, num, TT.cyan, dash); @@ -115,7 +121,7 @@ static int matchw(char *line, char *start, long so, long eo) static void do_grep(int fd, char *name) { long lcount = 0, mcount = 0, offset = 0, after = 0, before = 0, new = 1; - struct double_list *dlb = 0; + struct dlb *dlb = 0; char *bars = 0; FILE *file; int bin = 0; @@ -273,12 +279,10 @@ got: mm->rm_eo-mm->rm_so); else { while (dlb) { - struct double_list *dl = dlist_pop(&dlb); - unsigned *uu = (void *)(dl->data+(strlen(dl->data)|3)+1); + struct dlb *b = dlist_pop(&dlb); - outline(dl->data, '-', name, lcount-before, uu[0]+1, uu[1]); - free(dl->data); - free(dl); + outline(b->data, '-', name, lcount-before, b->bcount, b->trim); + free(b); before--; } @@ -315,20 +319,13 @@ got: discard = 0; } if (discard && TT.B) { - unsigned *uu, ul = (ulen|3)+1; - - line = xrealloc(line, ul+8); - uu = (void *)(line+ul); - uu[0] = offset-len; - uu[1] = ulen; - dlist_add(&dlb, line); - line = 0; - if (++before>TT.B) { - struct double_list *dl; + struct dlb *b = xmalloc(sizeof(struct dlb)+ulen); - dl = dlist_pop(&dlb); - free(dl->data); - free(dl); + b->bcount = offset-len+1; + memcpy(b->data, line, b->trim = ulen); + dlist_add_nomalloc((void *)&dlb, (void *)b); + if (++before>TT.B) { + free(dlist_pop(&dlb)); before--; } else discard = 0; } @@ -349,7 +346,7 @@ got: // loopfiles will also close the fd, but this frees an (opaque) struct. fclose(file); - llist_traverse(dlb, llist_free_double); + llist_traverse(dlb, free); } static int lensort(struct arg_list **a, struct arg_list **b) -- 2.39.5