Re: BUG #17053: Memory corruption in parser on prepared query reuse

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: demurgos(at)demurgos(dot)net
Cc: pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #17053: Memory corruption in parser on prepared query reuse
Date: 2021-06-09 21:41:36
Message-ID: 1509789.1623274896@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

PG Bug reporting form <noreply(at)postgresql(dot)org> writes:
> The code is fairly short, the core of the issue is that the prepared query
> `q1` is executed twice and it somehow messes up with the parser because of
> the `CHECK` clause.

Thanks for the report! The core of the problem is that where
transformExpr does this:

case T_NullTest:
{
NullTest *n = (NullTest *) expr;

n->arg = (Expr *) transformExprRecurse(pstate, (Node *) n->arg);

in the case of a prepared statement, it's scribbling on the same NullTest
node that's in the plan cache. So the next time we try to execute that
cache entry, the arg pointer is now pointing at garbage, or at least not
at the untransformed argument it should be pointing at.

Ideally, maybe, the parser wouldn't ever modify its input. However,
this code fragment has got LOTS of company, so making that happen has
never seemed too practical. So what we generally do, before invoking
the parser (or planner), is a quick copyObject() on any node tree that
might be coming from cache.

The proximate cause of this problem is that CREATE/ALTER DOMAIN did
not get that memo. Looking around in typecmds.c, I noted that
CREATE DOMAIN ... DEFAULT ... and ALTER DOMAIN SET DEFAULT have the
same kind of bug.

The attached patch seems to fix it. I wonder though if we ought to
move the copying to someplace more centralized. I cannot escape the
suspicion that there are more of these creepy-crawlies in other
poorly-tested utility statements.

BTW, a note for future testing: you can set up this failure using
pgbench, no custom client code required. I tested stuff like this:

$ cat bug17053b.sql
DROP DOMAIN IF EXISTS schema_meta;
CREATE DOMAIN schema_meta AS bool DEFAULT (42 IS NOT NULL);
$ pgbench -n -M prepared -f bug17053b.sql regression
NOTICE: type "schema_meta" does not exist, skipping
pgbench: error: client 0 script 0 aborted in command 1 query 0: ERROR: unrecognized node type: 2139062143

regards, tom lane

Attachment Content-Type Size
copy-raw-expressions-in-domain-DDL.patch text/x-diff 1.9 KB

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Michel Helms 2021-06-10 08:57:37 pg_table_size errors "invalid name syntax" for table names containing spaces
Previous Message PG Bug reporting form 2021-06-09 20:13:17 BUG #17053: Memory corruption in parser on prepared query reuse