summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorgrr <grr@cvs.openbsd.org>1997-08-06 23:44:12 +0000
committergrr <grr@cvs.openbsd.org>1997-08-06 23:44:12 +0000
commitad102259e12c348022abd6f89b959c64c3ea2bae (patch)
treefeea55774caa22fc7027d88b4a84d4928b216dc7 /gnu
parent54f04d186fef05a6650a7c2c77fa7690c100a604 (diff)
fix grep memory leak due due to using valloc to grow line buffer and be more conservative about growing buffer in the face of arbitrarily long lines
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/grep/Makefile5
-rw-r--r--gnu/usr.bin/grep/grep.16
-rw-r--r--gnu/usr.bin/grep/grep.c29
3 files changed, 30 insertions, 10 deletions
diff --git a/gnu/usr.bin/grep/Makefile b/gnu/usr.bin/grep/Makefile
index 3e454f7c6a1..188a8b8ed23 100644
--- a/gnu/usr.bin/grep/Makefile
+++ b/gnu/usr.bin/grep/Makefile
@@ -1,11 +1,10 @@
-# $OpenBSD: Makefile,v 1.2 1996/08/20 05:14:08 tholo Exp $
+# $OpenBSD: Makefile,v 1.3 1997/08/06 23:44:10 grr Exp $
# $NetBSD: Makefile,v 1.6 1995/04/23 07:58:41 cgd Exp $
PROG= grep
SRCS= dfa.c grep.c getopt.c kwset.c obstack.c regex.c search.c
CFLAGS+=-DGREP -DHAVE_STRING_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_UNISTD_H=1 \
- -DHAVE_GETPAGESIZE=1 -DHAVE_MEMCHR=1 -DHAVE_STRERROR=1 \
- -DHAVE_VALLOC=1
+ -DHAVE_GETPAGESIZE=1 -DHAVE_MEMCHR=1 -DHAVE_STRERROR=1 -DMULT=2
LINKS+= ${BINDIR}/grep ${BINDIR}/egrep \
${BINDIR}/grep ${BINDIR}/fgrep
diff --git a/gnu/usr.bin/grep/grep.1 b/gnu/usr.bin/grep/grep.1
index e9093ce8bf7..d8eccb2def5 100644
--- a/gnu/usr.bin/grep/grep.1
+++ b/gnu/usr.bin/grep/grep.1
@@ -1,4 +1,4 @@
-.\" $Id: grep.1,v 1.2 1997/07/08 09:47:01 deraadt Exp $ -*- nroff -*-
+.\" $Id: grep.1,v 1.3 1997/08/06 23:44:10 grr Exp $ -*- nroff -*-
.TH GREP 1 "1992 September 10" "GNU Project"
.SH NAME
grep, egrep, fgrep \- print lines matching a pattern
@@ -377,3 +377,7 @@ and space, and may cause
to run out of memory.
.PP
Backreferences are very slow, and may require exponential time.
+.PP
+Files which have extremely long sequences of characters without newlines
+may cause grep to run out of memory. An example is sparse files, which
+can read as arbritarily long sequences of nul characters.
diff --git a/gnu/usr.bin/grep/grep.c b/gnu/usr.bin/grep/grep.c
index aad5427c77f..37e6d19adfe 100644
--- a/gnu/usr.bin/grep/grep.c
+++ b/gnu/usr.bin/grep/grep.c
@@ -18,7 +18,7 @@
Written July 1992 by Mike Haertel. */
#ifndef lint
-static char rcsid[] = "$Id: grep.c,v 1.1 1995/10/18 08:40:17 deraadt Exp $";
+static char rcsid[] = "$Id: grep.c,v 1.2 1997/08/06 23:44:11 grr Exp $";
#endif /* not lint */
#include <errno.h>
@@ -171,15 +171,22 @@ xrealloc(ptr, size)
}
#if !defined(HAVE_VALLOC)
-#define valloc malloc
+#define valloc(x) malloc(x)
+#define vfree(x) free(x)
#else
#ifdef __STDC__
extern void *valloc(size_t);
+#define vfree(x) ;
#else
extern char *valloc();
+#define vfree(x) ;
#endif
#endif
+#ifndef MULT
+#define MULT 5
+#endif
+
/* Hairy buffering mechanism for grep. The intent is to keep
all reads aligned on a page boundary and multiples of the
page size. */
@@ -217,7 +224,7 @@ reset(fd)
#else
bufsalloc = BUFSALLOC;
#endif
- bufalloc = 5 * bufsalloc;
+ bufalloc = MULT * bufsalloc;
/* The 1 byte of overflow is a kludge for dfaexec(), which
inserts a sentinel newline at the end of the buffer
being searched. There's gotta be a better way... */
@@ -257,17 +264,25 @@ fillbuf(save)
if (pagesize == 0 && (pagesize = getpagesize()) == 0)
abort();
+ /* If the current line won't easily fit in the existing buffer
+ allocate a MULT larger one. This can result in running out
+ of memory on sparse files or those containing longs runs of
+ <nul>'s or other non-<nl> characters */
+
if (save > bufsalloc)
{
while (save > bufsalloc)
bufsalloc *= 2;
- bufalloc = 5 * bufsalloc;
+ bufalloc = MULT * bufsalloc;
nbuffer = valloc(bufalloc + 1);
if (!nbuffer)
fatal("memory exhausted", 0);
}
else
- nbuffer = buffer;
+ {
+ nbuffer = buffer;
+ buffer = NULL;
+ }
sp = buflim - save;
dp = nbuffer + bufsalloc - save;
@@ -276,8 +291,10 @@ fillbuf(save)
*dp++ = *sp++;
/* We may have allocated a new, larger buffer. Since
- there is no portable vfree(), we just have to forget
+ there is no portable vfree(), we may just have to forget
about the old one. Sorry. */
+ if (buffer != NULL)
+ vfree(buffer);
buffer = nbuffer;
#if defined(HAVE_WORKING_MMAP)