Prevent corner-case core dump in rfree().

rfree() failed to cope with the case that pg_regcomp() had initialized the
regex_t struct but then failed to allocate any memory for re->re_guts (ie,
the first malloc call in pg_regcomp() failed).  It would try to touch the
guts struct anyway, and thus dump core.  This is a sufficiently narrow
corner case that it's not surprising it's never been seen in the field;
but still a bug is a bug, so patch all active branches.

Noted while investigating whether we need to call pg_regfree after a
failure return from pg_regcomp.  Other than this bug, it turns out we
don't, so adjust comments appropriately.
This commit is contained in:
Tom Lane 2012-07-15 13:27:54 -04:00
parent 2686da9db2
commit 54fd196ffc
2 changed files with 16 additions and 11 deletions

View File

@ -278,6 +278,9 @@ static struct fns functions = {
/* /*
* pg_regcomp - compile regular expression * pg_regcomp - compile regular expression
*
* Note: on failure, no resources remain allocated, so pg_regfree()
* need not be applied to re.
*/ */
int int
pg_regcomp(regex_t *re, pg_regcomp(regex_t *re,
@ -1870,15 +1873,18 @@ rfree(regex_t *re)
g = (struct guts *) re->re_guts; g = (struct guts *) re->re_guts;
re->re_guts = NULL; re->re_guts = NULL;
re->re_fns = NULL; re->re_fns = NULL;
g->magic = 0; if (g != NULL)
freecm(&g->cmap); {
if (g->tree != NULL) g->magic = 0;
freesubre((struct vars *) NULL, g->tree); freecm(&g->cmap);
if (g->lacons != NULL) if (g->tree != NULL)
freelacons(g->lacons, g->nlacons); freesubre((struct vars *) NULL, g->tree);
if (!NULLCNFA(g->search)) if (g->lacons != NULL)
freecnfa(&g->search); freelacons(g->lacons, g->nlacons);
FREE(g); if (!NULLCNFA(g->search))
freecnfa(&g->search);
FREE(g);
}
} }
#ifdef REG_DEBUG #ifdef REG_DEBUG

View File

@ -187,9 +187,8 @@ RE_compile_and_cache(text *text_re, int cflags, Oid collation)
if (regcomp_result != REG_OKAY) if (regcomp_result != REG_OKAY)
{ {
/* re didn't compile */ /* re didn't compile (no need for pg_regfree, if so) */
pg_regerror(regcomp_result, &re_temp.cre_re, errMsg, sizeof(errMsg)); pg_regerror(regcomp_result, &re_temp.cre_re, errMsg, sizeof(errMsg));
/* XXX should we pg_regfree here? */
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION), (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
errmsg("invalid regular expression: %s", errMsg))); errmsg("invalid regular expression: %s", errMsg)));