Bug 26283

Summary: column coredumps on specific input
Product: Base System Reporter: enderle <enderle>
Component: binAssignee: dwmalone
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.2-STABLE   
Hardware: Any   
OS: Any   

Description enderle 2001-04-02 08:20:01 UTC
column coredumps on some input

How-To-Repeat: % printf "1\n2\n3\n4\n5\n6\n" | column -c 2
zsh: done                                    printf 1\n2\n3\n4\n5\n6\n |
zsh: floating point exception (core dumped)  column -c 2
Comment 1 Peter Pentchev 2001-04-02 09:11:20 UTC
On Mon, Apr 02, 2001 at 12:16:58AM -0700, enderle@mdn.de wrote:
> 
> >Number:         26283
> >Category:       bin
> >Synopsis:       column coredumps on specific input
> >Originator:     Steven Enderle
> >Release:        4.2-STABLE
> >Organization:
> mdn Hübner GmbH
> >Environment:
> FreeBSD BSD03 4.2-STABLE FreeBSD 4.2-STABLE #0: Mon Dec  4 16:34:57 CET 2000     root@BSD03:/usr/src/sys/compile/BSD03  i386
> >Description:
> column coredumps on some input
> >How-To-Repeat:
> % printf "1\n2\n3\n4\n5\n6\n" | column -c 2
> zsh: done                                    printf 1\n2\n3\n4\n5\n6\n |
> zsh: floating point exception (core dumped)  column -c 2

Hmm.  It would seem that the problem is that maxlength is TAB-aligned
after the maxlength > termwidth check, and *then* the number of columns
is calculated as termwidth / maxlength.  In the case of termwidth < TAB,
this leads to numcols = 0 (termwidth / TAB).

Could you try the following patch?  It works for me..
(As a side point, maybe the tab-size should be configurable.. but that's
 another battle ;)

G'luck,
Peter

-- 
I am the meaning of this sentence.

Index: src/usr.bin/column/column.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/column/column.c,v
retrieving revision 1.4
diff -u -r1.4 column.c
--- src/usr.bin/column/column.c	1998/12/06 22:58:18	1.4
+++ src/usr.bin/column/column.c	2001/04/02 08:08:38
@@ -52,6 +52,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#define	TAB	8
+
 void  c_columnate __P((void));
 void *emalloc __P((int));
 void  input __P((FILE *));
@@ -122,7 +124,7 @@
 
 	if (tflag)
 		maketbl();
-	else if (maxlength >= termwidth)
+	else if ((maxlength >= termwidth) || (termwidth < TAB))
 		print();
 	else if (xflag)
 		c_columnate();
@@ -131,7 +133,6 @@
 	exit(eval);
 }
 
-#define	TAB	8
 void
 c_columnate()
 {
Comment 2 Peter Pentchev 2001-04-02 09:38:51 UTC
On Mon, Apr 02, 2001 at 09:26:21AM +0100, David Malone wrote:
> On Mon, Apr 02, 2001 at 01:20:03AM -0700, Peter Pentchev wrote:
> 
> >  Could you try the following patch?  It works for me..
> >  (As a side point, maybe the tab-size should be configurable.. but that's
> >   another battle ;)
> 
> I think that this leaves the problem open in some other cases.
> Try:
> 
> 	echo "aaaaaaaaaaaa" | ./column -c 15
> 
> maxlength probably needs to be rounded up to the nearest tabstop
> before the test is carried out.

Yes, that was my first idea; I can't really remember what was wrong
with it, why didn't I fix it that way :)

Updated patch follows..

As another side point, column -t (table mode) seems to just ignore
the terminal size.. is that The Right Thing (tm)?

G'luck,
Peter

-- 
.siht ekil ti gnidaer eb d'uoy ,werbeH ni erew ecnetnes siht fI

Index: src/usr.bin/column/column.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/column/column.c,v
retrieving revision 1.4
diff -u -r1.4 column.c
--- src/usr.bin/column/column.c	1998/12/06 22:58:18	1.4
+++ src/usr.bin/column/column.c	2001/04/02 08:37:21
@@ -52,6 +52,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#define	TAB	8
+
 void  c_columnate __P((void));
 void *emalloc __P((int));
 void  input __P((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()
 {
 	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)
Comment 3 Peter Pentchev 2001-04-02 10:48:36 UTC
On Mon, Apr 02, 2001 at 11:24:47AM +0200, Steven Enderle wrote:
> This still doesn't help me much ... maybe it is not bug related, more
> user stupidy,
> but i will show you what i want to do:
> 
> The following few lines (take 100.000 more and you got what i am sitting
> in front of) should be formated into two columns:
> 
> --- snip ---
> 90 4y 8289!  182 !  464 !              !
> 90 4y 8289!  182 !  464 !              !
> 90 4y 8289!  182 !  464 !              !
> 90 4y 8289!  182 !  464 !              !
> --- snip ---
> 
> so that the result looks like this:
> 
> --- snip ---
> 90 4y 8289!  182 !  464 !              !90 4y 8289!  182 !  464
> !              !
> 90 4y 8289!  182 !  464 !              !90 4y 8289!  182 !  464
> !              !
> --- snip ---
> 
> (printf '90 4y 8289!  182 !  464 !              !\n90 4y 8289!  182 ! 
> 464 !              !\n90 4y 8289!  182 !  464 !              !\n90 4y
> 8289!  182 !  464 !              !\n' will give you the sample i am
> working with.)
> 
> so i thought, column -c 2 should do it. ("-c      Output is formatted
> for a display columns wide.")
[snip]
> is column that buggy? or am i too stupid to handle column correctly?
> is there any other easy way to do this?

Uhh.. column(1) doesn't work that way.  The '-c' option is meant to
specify how many characters should there be in one line; think of
a display 80 columns wide - that's what -c 80 would be.  By putting
-c 2 in there, you are telling column(1) that it should format its
output for 2 chars per line; it finds that most lines are longer
than 2 chars, so it just displays them as-is.

If all your lines have a fixed width, you should probably use
column with -c, but with a value just a bit more than twice
your line width.  However, your lines seem to be exactly 40 chars
wide, which poses a problem - column(1) likes to add a tab between
the columns.  You might get away with something like:

column -c 96 < yourfile | tr -d '\t'

..or..

column -c 96 < yourfile | perl -pe 's/!\t/!/g'

(I couldn't figure out the sed(1) escape sequence for a tab).

The 96 comes from 40 chars-line + tab = 48 chars.. to fit two of those
on a line, you need 96 chars per line.

Hope that helps..

G'luck,
Peter

-- 
No language can express every thought unambiguously, least of all this one.
Comment 4 dwmalone freebsd_committer freebsd_triage 2001-04-03 19:06:08 UTC
Responsible Changed
From-To: freebsd-bugs->dwmalone

I've committed Peter's fix to -current and will merge to -stable soon. 
.
Comment 5 dwmalone freebsd_committer freebsd_triage 2001-04-30 09:37:50 UTC
State Changed
From-To: open->closed

Merged by Kris.