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)

Reply via email to