Skip to content

Commit c028577

Browse files
committed
Don't capture hard errors in with-clause parser
When parsing WITH clause arguments for ALTER TABLE to extract compression parameters, syntax errors in the text format are caught using PG_TRY and PG_CATCH and then returning an indication if the parse succeeded or not. If an out-of-memory error occurs inside execution of the input function and this error is caught, it can continue executing and potentially cause cascading out-of-memory errors and in the end exhausting the error stack. This commit solves this by using checking the category of the thrown error and only allow errors in the data exception and the syntax errors and access rules violation category, which are "soft" errors in this case. Hard errors, like out-of-memory errors, are re-thrown allowing the backend to deal with it properly.
1 parent 4653c72 commit c028577

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

.unreleased/pr_7893

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixes: #7893 Don't capture hard errors in with-clause parser

src/with_clause_parser.c

+26
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,38 @@ parse_arg(WithClauseDefinition arg, DefElem *def)
161161

162162
Assert(OidIsValid(in_fn));
163163

164+
/*
165+
* We could use InputFunctionCallSafe() here but this is just supported
166+
* for PG16 and later, so we opt for checking if the failure is what we
167+
* expected and re-throwing the error otherwise.
168+
*/
164169
PG_TRY();
165170
{
166171
val = OidInputFunctionCall(in_fn, value, typIOParam, -1);
167172
}
168173
PG_CATCH();
169174
{
175+
const int sqlerrcode = geterrcode();
176+
/*
177+
* We can deal with the Data Exception category and in the Syntax
178+
* Error or Access Rule Violation category, but if the error is an
179+
* insufficient resources category, for example, an out of memory
180+
* error, we should just re-throw it.
181+
*
182+
* Errors in other categories are unlikely, but we cannot do anything
183+
* with them anyway, so just re-throw them as well.
184+
*/
185+
if (ERRCODE_TO_CATEGORY(sqlerrcode) != ERRCODE_DATA_EXCEPTION &&
186+
ERRCODE_TO_CATEGORY(sqlerrcode) != ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION)
187+
{
188+
PG_RE_THROW();
189+
}
190+
FlushErrorState();
191+
192+
/* We are currently using the ErrorContext, but since we are going to
193+
* raise an error later, there is no reason to switch memory context
194+
* nor restore the resource owner here. */
195+
170196
Form_pg_type typetup;
171197
HeapTuple tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arg.type_id));
172198
if (!HeapTupleIsValid(tup))

0 commit comments

Comments
 (0)