From: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> |
---|---|
To: | pgsql-hackers(at)lists(dot)postgresql(dot)org |
Subject: | Making pgfdw_report_error statically analyzable |
Date: | 2025-07-28 14:54:51 |
Message-ID: | 420221.1753714491@sss.pgh.pa.us |
Views: | Whole Thread | Raw Message | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
In the wake of commits 7d8f59577+80aa9848b, Coverity has begun
bleating like this:
*** CID 1659393: Memory - illegal accesses (USE_AFTER_FREE)
/srv/coverity/git/pgsql-git/postgresql/contrib/postgres_fdw/postgres_fdw.c: 4930 in postgresAnalyzeForeignTable()
4924 res = pgfdw_exec_query(conn, sql.data, NULL);
4925 if (PQresultStatus(res) != PGRES_TUPLES_OK)
4926 pgfdw_report_error(ERROR, res, conn, sql.data);
4927
4928 if (PQntuples(res) != 1 || PQnfields(res) != 1)
4929 elog(ERROR, "unexpected result from deparseAnalyzeSizeSql query");
>>> CID 1659393: Memory - illegal accesses (USE_AFTER_FREE)
>>> Calling "libpqsrv_PQgetvalue" dereferences freed pointer "res->res".
4930 *totalpages = strtoul(PQgetvalue(res, 0, 0), NULL, 10);
4931 PQclear(res);
4932
4933 ReleaseConnection(conn);
4934
4935 return true;
(and similarly in other places in postgres_fdw). Now, this complaint
is nonsense because we won't get past the PQresultStatus and
pgfdw_report_error bit if we don't have a fully valid PGresult.
Evidently, Coverity is not managing to figure out that
pgfdw_report_error(ERROR, ...) doesn't return. That's a bit
surprising because it normally does fairly deep interprocedural
analysis, but the conclusion is hard to avoid. Certainly, any
C compiler that doesn't do deep LTO is not going to figure it
out either. I think we have previously just dismissed similar
Coverity complaints, but it seems like we ought to try to fix
it properly this time.
I can see two, or two-and-a-half, ways to do that:
1. Wrap pgfdw_report_error in a macro that makes use of pg_unreachable
in a way similar to what we've done for elog/ereport. The argument
for this is that we needn't touch the 30-or-so pgfdw_report_error
call sites; the argument against is that those elog/ereport macros
are messy, compiler-dependent, and keep needing changes.
2a. Split pgfdw_report_error into two functions, say
pgfdw_report_error() that hard-wires elevel as ERROR and is
labeled noreturn, and pgfdw_report_noerror() that has an
elevel argument that it asserts is less than ERROR.
2b. As 2a except the two functions are pgfdw_report_error()
and pgfdw_report_warning(), both with hard-wired elevel values.
This'd be sufficient right now, but it's plausible that this path
would lead to needing pgfdw_report_log() and some other variants
in future.
The argument for 2a/2b is that they're really simple and are
unlikely to break in the future. The argument against is that
the changes would create back-patching hazards --- but maybe
it'd be reasonable to back-patch the changes to forestall that.
I'm kind of leaning to doing 2a and back-patching it, but
that's certainly a judgment call. Anyone want to argue
for a different approach?
regards, tom lane
From | Date | Subject | |
---|---|---|---|
Next Message | Frédéric Yhuel | 2025-07-28 15:09:15 | Re: vacuumdb changes for stats import/export |
Previous Message | Nathan Bossart | 2025-07-28 14:47:22 | Re: vacuumdb changes for stats import/export |