Thread
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Avoid scribbling on input node tree in CREATE/ALTER DOMAIN.
- f172438ef6ff 10.18 landed
- b2c740c426da 12.8 landed
- 4b8b3562e1e6 11.13 landed
- 1a3d30255a4e 9.6.23 landed
- 102f31a208b8 13.4 landed
-
Centralize the logic for protective copying of utility statements.
- 7c337b6b527b 14.0 landed
-
BUG #17053: Memory corruption in parser on prepared query reuse
PG Bug reporting form <noreply@postgresql.org> — 2021-06-09T20:13:17Z
The following bug has been logged on the website: Bug reference: 17053 Logged by: Charles Samborski Email address: demurgos@demurgos.net PostgreSQL version: 13.3 Operating system: Linux 5.12 (Arch Linux) Description: I found a bug in Postgres where I can reliably trigger the following error: "unrecognized node type: X", where X can be anything and changes across program executions. For example, I can get "unrecognized node type: 0", "nrecognized node type: 184", "unrecognized node type: 196608" and many others (including negative values). This implies that a node type is read from a corrupted memory location. The following repo has C and Rust programs exhibiting this behavior: https://github.com/demurgos/pg_unrecognized_node. Here is the C program: ``` #include <stdio.h> #include <stdlib.h> #include "libpq-fe.h" int main(int argc, char **argv) { PGconn *conn; PGresult *res; conn = PQconnectdb(""); PQexec(conn, "DROP DOMAIN IF EXISTS schema_meta"); PQexec(conn, "CREATE TYPE raw_schema_meta AS (version int4)"); PQprepare(conn, "q1", "CREATE DOMAIN schema_meta AS raw_schema_meta CHECK ((value).version IS NOT NULL AND (value).version >= 1)", 0, NULL); PQexecPrepared(conn, "q1", 0, NULL, 0, 0, 0); PQexec(conn, "DROP DOMAIN IF EXISTS schema_meta"); res = PQexecPrepared(conn, "q1", 0, NULL, 0, 0, 0); fprintf(stdout, "%s", PQresultErrorMessage(res)); PQfinish(conn); return 0; } ``` You can compile it with `gcc -lpq -o main main.c` and run it on fresh DB by passing the credentials through the environment, e.g.: `PGUSER=test PGPASSWORD=test PGDATABASE=test ./main` I investigated this issue with the help of some people from IRC and would like to thank them: ioguix, johto and Zr40. 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. -
Re: BUG #17053: Memory corruption in parser on prepared query reuse
Tom Lane <tgl@sss.pgh.pa.us> — 2021-06-09T21:41:36Z
PG Bug reporting form <noreply@postgresql.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 -
Re: BUG #17053: Memory corruption in parser on prepared query reuse
Charles Samborski <demurgos@demurgos.net> — 2021-08-19T13:07:35Z
I am not familiar with how Postgres tracks its bugs. How can I check the status of this bug #17053? Is it still pending? > 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. Is the quick-fix already applied or do you want to wait for these larger changes? I was hoping to drop my workarounds once the fixes for this bug land. Regards, Charles Samborski
-
Re: BUG #17053: Memory corruption in parser on prepared query reuse
Tom Lane <tgl@sss.pgh.pa.us> — 2021-08-19T14:34:54Z
Charles Samborski <demurgos@demurgos.net> writes: > I am not familiar with how Postgres tracks its bugs. How can I check the > status of this bug #17053? Is it still pending? The fix was pushed in the releases made earlier this month. regards, tom lane