Subject: lib/14975: regexec(3) memory leak
To: None <gnats-bugs@gnats.netbsd.org>
From: None <t-kouchi@mud.biglobe.ne.jp>
List: netbsd-bugs
Date: 12/16/2001 22:07:09
>Number: 14975
>Category: lib
>Synopsis: regexec(3) memory leak
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Dec 16 22:07:00 PST 2001
>Closed-Date:
>Last-Modified:
>Originator: Takayoshi Kochi
>Release: 1.5.2
>Organization:
>Environment:
NetBSD vmnetbsd 1.5.2 NetBSD 1.5.2 (VMWARE) #6: Mon Oct 15 01:05:38 PDT 2001 kochi@vmnetbsd:/usr/src/sys/arch/i386/compile/VMWARE i386
>Description:
I'm hit by a memory leak problem in regexec(3) on 1.5 and very
recent 1.5-current.
This case is easily repeatable by attached program.
If you give it a regular expression (e.g. '^[a-z]+'), the program
searches the pattern against the same string forever.
In special case, when I give it '\(.\)\1\1\1' (any 4 sequential
characters), its size will be increasing to its limit (which
can be monitord by top(1)).
But strangely, when I give '\(.\)\1\1' (any 3 sequential characters)
the problem won't occur.
>How-To-Repeat:
run this program with argument '\(.\)\1\1\1'.
----------------
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <regex.h>
main(int argc, char *argv[])
{
int c, ret, cflags;
regex_t re;
char buf[BUFSIZ];
cflags = REG_ICASE;
while(1) {
ret = regcomp(&re, argv[1], cflags);
if (ret) {
regerror(ret, &re, buf, BUFSIZ);
fprintf(stderr, "%s\n", buf);
regfree(&re);
exit(1);
}
ret = regexec(&re, "bbbddeeefffefjaidf", 0, 0, 0);
regfree(&re);
}
}
>Fix:
enami-san gave me a quick patch for this problem.
It seems that my problem is fixed with this patch.
------------
Date: Mon, 10 Dec 2001 15:23:18 +0900 (JST)
Message-Id: <200112100623.PAA03524@decoy.but-b.or.jp>
At a first glance, following free()s are missing.
enami.
Index: engine.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/regex/engine.c,v
retrieving revision 1.12
diff -u -r1.12 engine.c
--- engine.c 1999/09/16 11:45:20 1.12
+++ engine.c 2001/12/10 06:17:25
@@ -202,6 +202,10 @@
for (;;) {
endp = fast(m, start, stop, gf, gl);
if (endp == NULL) { /* a miss */
+ if (m->pmatch != NULL)
+ free(m->pmatch);
+ if (m->lastpos != NULL)
+ free(m->lastpos);
STATETEARDOWN(m);
return(REG_NOMATCH);
}
>Release-Note:
>Audit-Trail:
>Unformatted: