Subject: bug#17328: dfa.c will fail if used on more than one DFA

From: Paul Eggert <[email-masked]>
Date: Wed, 23 Apr 2014 23:23:20 -0700

Thanks.  We can improve on that a bit, by using one of the pointers to 
indicate whether the storage is allocated, instead of requiring an extra 
boolean for this information.  I pushed the attached patch.
From c5a83dbb9596c98a260af9b545fc64a57b59be60 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Wed, 23 Apr 2014 23:20:35 -0700
Subject: [PATCH] dfa: fix memory leak reintroduced by previous patch

Reported by Norihiro Tanaka in <http://bugs.gnu.org/17328#16>.
* src/dfa.c (dfaexec): Allocate mb_match_lens and mb_follows only
if not already allocated.
(free_mbdata): Null out mb_match_lens to mark it as being freed.
---
 src/dfa.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/dfa.c b/src/dfa.c
index 42a9736..5dc0f09 100644
--- a/src/dfa.c
+++ b/src/dfa.c
@@ -426,7 +426,8 @@ struct dfa
   position_set mb_follows;	/* Follow set added by ANYCHAR and/or MBCSET
                                    on demand.  */
   int *mb_match_lens;           /* Array of length reduced by ANYCHAR and/or
-                                   MBCSET.  */
+                                   MBCSET.  Null if mb_follows.elems has not
+                                   been allocated.  */
 };
 
 /* Some macros for user access to dfa internals.  */
@@ -3245,8 +3246,11 @@ dfaexec (struct dfa *d, char const *begin, char *end,
   if (d->mb_cur_max > 1)
     {
       memset (&d->mbs, 0, sizeof d->mbs);
-      d->mb_match_lens = xnmalloc (d->nleaves, sizeof *d->mb_match_lens);
-      alloc_position_set (&d->mb_follows, d->nleaves);
+      if (! d->mb_match_lens)
+        {
+          d->mb_match_lens = xnmalloc (d->nleaves, sizeof *d->mb_match_lens);
+          alloc_position_set (&d->mb_follows, d->nleaves);
+        }
     }
 
   for (;;)
@@ -3422,6 +3426,7 @@ free_mbdata (struct dfa *d)
   free (d->mbcsets);
   free (d->mb_follows.elems);
   free (d->mb_match_lens);
+  d->mb_match_lens = NULL;
 }
 
 /* Initialize the components of a dfa that the other routines don't
-- 
1.9.0