]> granicus.if.org Git - postgresql/commitdiff
Fix minor bug in regexp makesearch() function.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 10 Sep 2015 00:14:58 +0000 (20:14 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 10 Sep 2015 00:15:26 +0000 (20:15 -0400)
The list-wrangling here was done wrong, allowing the same state to get
put into the list twice.  The following loop then would clone it twice.
The second clone would wind up with no inarcs, so that there was no
observable misbehavior AFAICT, but a useless state in the finished NFA
isn't an especially good thing.

src/backend/regex/regcomp.c

index f1539e726a7a3a592ca588800b3cb2d2f27703f8..671151bfc88a5c20b13af184fc53eba0cabc22f8 100644 (file)
@@ -567,21 +567,26 @@ makesearch(struct vars * v,
         * splitting each such state into progress and no-progress states.
         */
 
-       /* first, make a list of the states */
+       /* first, make a list of the states reachable from pre and elsewhere */
        slist = NULL;
        for (a = pre->outs; a != NULL; a = a->outchain)
        {
                s = a->to;
                for (b = s->ins; b != NULL; b = b->inchain)
+               {
                        if (b->from != pre)
                                break;
+               }
+
+               /*
+                * We want to mark states as being in the list already by having non
+                * NULL tmp fields, but we can't just store the old slist value in tmp
+                * because that doesn't work for the first such state.  Instead, the
+                * first list entry gets its own address in tmp.
+                */
                if (b != NULL && s->tmp == NULL)
                {
-                       /*
-                        * Must be split if not already in the list (fixes bugs 505048,
-                        * 230589, 840258, 504785).
-                        */
-                       s->tmp = slist;
+                       s->tmp = (slist != NULL) ? slist : s;
                        slist = s;
                }
        }
@@ -600,7 +605,7 @@ makesearch(struct vars * v,
                                freearc(nfa, a);
                        }
                }
-               s2 = s->tmp;
+               s2 = (s->tmp != s) ? s->tmp : NULL;
                s->tmp = NULL;                  /* clean up while we're at it */
        }
 }