Subject: bin/8184: /usr/bin/join crashes with SIGSEGV
To: None <email@example.com>
From: None <firstname.lastname@example.org>
Date: 08/10/1999 07:22:04
>Synopsis: join crashes under certain circumstances due to a wrong memmove operation
>Responsible: bin-bug-people (Utility Bug People)
>Arrival-Date: Tue Aug 10 04:20:01 1999
= Tel.: +49-681-302-5571 = Universitaet des Saarlandes =
= Fax.: +49-681-302-3065 = Postfach 15 11 50 =
= Compiler Research Group = 66041 Saarbruecken =
= FB 14 - Informatik = GERMANY =
>Release: NetBSD-current 090899
System: NetBSD gargoyle.cs.uni-sb.de 1.4J NetBSD 1.4J (Gargoyle) #0: Sun Aug 8 21:39:47 CEST 1999 email@example.com:/usr/src/sys/arch/i386/compile/Gargoyle i386
join crashes due to an access to an invalid memory location.
Why this happens:
join reads lines from a FILE via the fgetln function, which returns
a pointer into the buffer allocated by the FILE stream and the length
of the line.
The line is then copied to a user allocated buffer via memmove.
Since fgetln does not append a '\0' to the line it reads (and does
not count it in the returned length) one additional byte has to be
allocated for the user buffer, so the NUL char can be appended.
Unfortunately, the memmove function is told to copy length+1 bytes from
the internal buffer to the user buffer. In the rare circumstance, where
the line ends exactly at the end of the internal FILE buffer (and the page
following the buffer is not allocated ) reading this extra byte causes
an access to an illegal page and join crashes.
Create input files which causes a line read to end exactly at the
end of the internal buffer and do something like
join -111 -211 -v2 a b
I came across this, since /etc/security dumped core. security uses join
to list the difference between e.g. suid files across invocations.
The following patch should fix this problem (and also includes a minor
correction for a call to memset, which uses the wrong size)
--- /usr/src/usr.bin/join/join.c.orig Sun Dec 20 13:17:41 1998
+++ /usr/src/usr.bin/join/join.c Tue Aug 10 12:37:17 1999
@@ -317,7 +317,7 @@
if ((F->set = realloc(F->set,
F->setalloc * sizeof(LINE))) == NULL)
- memset(F->set + cnt, 0, 100 * sizeof(LINE *));
+ memset(F->set + cnt, 0, 100 * sizeof(LINE));
@@ -347,7 +347,7 @@
lp->linealloc * sizeof(char))) == NULL)
- memmove(lp->line, bp, len+1);
+ memmove(lp->line, bp, len);
/* Replace trailing newline, if it exists. */
if (bp[len - 1] == '\n')