Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1567e65

Browse files
committed
Fix two low-probability memory leaks in regular expression parsing.
If pg_regcomp failed after having invoked markst/cleanst, it would leak any "struct subre" nodes it had created. (We've already detected all regex syntax errors at that point, so the only likely causes of later failure would be query cancel or out-of-memory.) To fix, make sure freesrnode knows the difference between the pre-cleanst and post-cleanst cleanup procedures. Add some documentation of this less-than-obvious point. Also, newlacon did the wrong thing with an out-of-memory failure from realloc(), so that the previously allocated array would be leaked. Both of these are pretty low-probability scenarios, but a bug is a bug, so patch all the way back. Per bug #10976 from Arthur O'Dwyer.
1 parent 6cd471a commit 1567e65

File tree

1 file changed

+24
-7
lines changed

1 file changed

+24
-7
lines changed

src/backend/regex/regcomp.c

+24-7
Original file line numberDiff line numberDiff line change
@@ -1680,8 +1680,9 @@ freesrnode(struct vars * v, /* might be NULL */
16801680
freecnfa(&sr->cnfa);
16811681
sr->flags = 0;
16821682

1683-
if (v != NULL)
1683+
if (v != NULL && v->treechain != NULL)
16841684
{
1685+
/* we're still parsing, maybe we can reuse the subre */
16851686
sr->left = v->treefree;
16861687
v->treefree = sr;
16871688
}
@@ -1727,6 +1728,20 @@ numst(struct subre * t,
17271728

17281729
/*
17291730
* markst - mark tree nodes as INUSE
1731+
*
1732+
* Note: this is a great deal more subtle than it looks. During initial
1733+
* parsing of a regex, all subres are linked into the treechain list;
1734+
* discarded ones are also linked into the treefree list for possible reuse.
1735+
* After we are done creating all subres required for a regex, we run markst()
1736+
* then cleanst(), which results in discarding all subres not reachable from
1737+
* v->tree. We then clear v->treechain, indicating that subres must be found
1738+
* by descending from v->tree. This changes the behavior of freesubre(): it
1739+
* will henceforth FREE() unwanted subres rather than sticking them into the
1740+
* treefree list. (Doing that any earlier would result in dangling links in
1741+
* the treechain list.) This all means that freev() will clean up correctly
1742+
* if invoked before or after markst()+cleanst(); but it would not work if
1743+
* called partway through this state conversion, so we mustn't error out
1744+
* in or between these two functions.
17301745
*/
17311746
static void
17321747
markst(struct subre * t)
@@ -1824,25 +1839,27 @@ newlacon(struct vars * v,
18241839
int pos)
18251840
{
18261841
int n;
1842+
struct subre *newlacons;
18271843
struct subre *sub;
18281844

18291845
if (v->nlacons == 0)
18301846
{
1831-
v->lacons = (struct subre *) MALLOC(2 * sizeof(struct subre));
18321847
n = 1; /* skip 0th */
1833-
v->nlacons = 2;
1848+
newlacons = (struct subre *) MALLOC(2 * sizeof(struct subre));
18341849
}
18351850
else
18361851
{
1837-
v->lacons = (struct subre *) REALLOC(v->lacons,
1838-
(v->nlacons + 1) * sizeof(struct subre));
1839-
n = v->nlacons++;
1852+
n = v->nlacons;
1853+
newlacons = (struct subre *) REALLOC(v->lacons,
1854+
(n + 1) * sizeof(struct subre));
18401855
}
1841-
if (v->lacons == NULL)
1856+
if (newlacons == NULL)
18421857
{
18431858
ERR(REG_ESPACE);
18441859
return 0;
18451860
}
1861+
v->lacons = newlacons;
1862+
v->nlacons = n + 1;
18461863
sub = &v->lacons[n];
18471864
sub->begin = begin;
18481865
sub->end = end;

0 commit comments

Comments
 (0)