diff options
author | grr <grr@cvs.openbsd.org> | 1997-08-06 23:44:12 +0000 |
---|---|---|
committer | grr <grr@cvs.openbsd.org> | 1997-08-06 23:44:12 +0000 |
commit | ad102259e12c348022abd6f89b959c64c3ea2bae (patch) | |
tree | feea55774caa22fc7027d88b4a84d4928b216dc7 /gnu | |
parent | 54f04d186fef05a6650a7c2c77fa7690c100a604 (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/Makefile | 5 | ||||
-rw-r--r-- | gnu/usr.bin/grep/grep.1 | 6 | ||||
-rw-r--r-- | gnu/usr.bin/grep/grep.c | 29 |
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) |