On Thu, Apr 02, 2026, Martijn van Duren wrote:
> Can you look at where these come from?
You are right, the NULL check was wrong.
flush_lines(extra_lines) at line 299 frees from the list head,
but l still points to a freed node. The loop at line 302
follows l->l_next through freed heap, giving the bogus count.
Also, this_line keeps the negative offset from the prepends.
Fix: reset l and undo the offset after flushing the extra lines.
Fuzzing with random \v inputs on OpenBSD 7.9/amd64 with UBSan
shows a crash rate of ~14% without the fix and ~2% with it.
The remaining crashes appear to be other pre-existing accounting
issues. I will investigate those separately.
Index: usr.bin/col/col.c
===================================================================
RCS file: /cvs/src/usr.bin/col/col.c,v
retrieving revision 1.20
diff -u -p -r1.20 col.c
--- usr.bin/col/col.c 4 Dec 2022 23:50:47 -0000 1.20
+++ usr.bin/col/col.c
@@ -295,8 +295,11 @@ main(int argc, char *argv[])
l->l_max_col = cur_col;
cur_col++;
}
- if (extra_lines)
+ if (extra_lines) {
flush_lines(extra_lines);
+ l = lines;
+ this_line += extra_lines;
+ }
/* goto the last line that had a character on it */
for (; l->l_next; l = l->l_next)