Skip to content

Commit 7fc20c2

Browse files
committed
Run input function allowing soft errors only
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 31e8298 commit 7fc20c2

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

.unreleased/pr_7893

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixes: #7893 Run input function only allowing soft errors

src/with_clause_parser.c

+25
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ parse_arg(WithClauseDefinition arg, DefElem *def)
140140
Datum val;
141141
Oid in_fn;
142142
Oid typIOParam;
143+
MemoryContext ccxt = CurrentMemoryContext;
143144

144145
if (!OidIsValid(arg.type_id))
145146
ereport(ERROR,
@@ -161,12 +162,36 @@ parse_arg(WithClauseDefinition arg, DefElem *def)
161162

162163
Assert(OidIsValid(in_fn));
163164

165+
/*
166+
* We could use InputFunctionCallSafe() here but this is just supported
167+
* for PG16 and later, so we opt for checking if the failure is what we
168+
* expected and re-throwing the error otherwise.
169+
*/
164170
PG_TRY();
165171
{
166172
val = OidInputFunctionCall(in_fn, value, typIOParam, -1);
167173
}
168174
PG_CATCH();
169175
{
176+
MemoryContext ecxt = MemoryContextSwitchTo(ccxt);
177+
ErrorData *edata = CopyErrorData();
178+
/*
179+
* We can deal with the Data Exception category and in the Syntax
180+
* Error or Access Rule Violation category, but if the error is an
181+
* insufficient resources category, for example, an out of memory
182+
* error, we should just re-throw it.
183+
*
184+
* Errors in other categories are unlikely, but we cannot do anything
185+
* with them anyway, so just re-throw them as well.
186+
*/
187+
if (ERRCODE_TO_CATEGORY(edata->sqlerrcode) != ERRCODE_DATA_EXCEPTION &&
188+
ERRCODE_TO_CATEGORY(edata->sqlerrcode) != ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION)
189+
{
190+
FreeErrorData(edata);
191+
MemoryContextSwitchTo(ecxt);
192+
PG_RE_THROW();
193+
}
194+
170195
Form_pg_type typetup;
171196
HeapTuple tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arg.type_id));
172197
if (!HeapTupleIsValid(tup))

0 commit comments

Comments
 (0)