Subject: bin/32322: Division by zero in column(1) with certain column widths
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <daniel@netbsd.org>
List: netbsd-bugs
Date: 12/17/2005 16:10:00
>Number:         32322
>Category:       bin
>Synopsis:       Division by zero in column(1) with certain column widths
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Dec 17 16:10:00 +0000 2005
>Originator:     Daniel de Kok
>Release:        NetBSD 3.0RC6
>Organization:
>Environment:
NetBSD terrapin.taickim.net 3.0_RC6 NetBSD 3.0_RC6 (GENERIC) #0: Fri Dec  9 09:39:00 UTC 2005  riz@faith.netbsd.org:/home/builds/ab/netbsd-3-0-RC6/i386/200512090458Z-obj/home/builds/ab/netbsd-3-0-RC6/src/sys/arch/i386/compile/GENERIC i386
>Description:
column(1) core dumps when the column width is smaller than or equal to maxlength, because the rounding up of the line length is done after the safety checks, causing a division by zero. This also applies to -current.

Could someone with userland expertise review the attached patch?
>How-To-Repeat:
$ ls
GNUstep   muziek    netbsd    source    unixbook

$ ls | column -c 10
Floating point exception (core dumped)

#0  0x08048ee9 in r_columnate () at column.c:171
171             numrows = entries / numcols;
(gdb) bt full
#0  0x08048ee9 in r_columnate () at column.c:171
        base = -1077941812
        chcnt = 134523112
        cnt = 134515936
        col = -1077941912
        endcol = -1077941812
        numcols = 0
        numrows = 8
        row = -1077944056
#1  0x08048d9d in main (argc=0, argv=0xbfbfe9d8) at column.c:130
        win = {ws_row = 24, ws_col = 80, ws_xpixel = 499, ws_ypixel = 316}
        fp = (FILE *) 0x804a84c
        ch = -1
        tflag = 0
        xflag = 0
        p = 0xbdbdaef0 ",\036\v"
#2  0x080489e6 in ___start ()
>Fix:
Index: column.c
===================================================================
RCS file: /cvsroot/src/usr.bin/column/column.c,v
retrieving revision 1.12
diff -b -u -r1.12 column.c
--- column.c    17 Feb 2005 17:17:25 -0000      1.12
+++ column.c    17 Dec 2005 15:52:55 -0000
@@ -54,6 +54,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#define        TAB     8
+
 void  c_columnate(void);
 void *emalloc(int);
 void  input(FILE *);
@@ -120,6 +122,7 @@
        if (!entries)
                exit(eval);
 
+       maxlength = (maxlength + TAB) & ~(TAB - 1);
        if (tflag)
                maketbl();
        else if (maxlength >= termwidth)
@@ -131,14 +134,12 @@
        exit(eval);
 }
 
-#define        TAB     8
 void
 c_columnate(void)
 {
        int chcnt, col, cnt, endcol, numcols;
        char **lp;
 
-       maxlength = (maxlength + TAB) & ~(TAB - 1);
        numcols = termwidth / maxlength;
        endcol = maxlength;
        for (chcnt = col = 0, lp = list;; ++lp) {
@@ -166,7 +167,6 @@
 {
        int base, chcnt, cnt, col, endcol, numcols, numrows, row;
 
-       maxlength = (maxlength + TAB) & ~(TAB - 1);
        numcols = termwidth / maxlength;
        numrows = entries / numcols;
        if (entries % numcols)