| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | kehan5800(at)gmail(dot)com |
| Subject: | BUG #19745: tsquery input: 33 nested "!" raise XX000 via elog(), escaping pg_input_is_valid() |
| Date: | 2026-10-04 05:17:04 |
| Message-ID: | 19745-39cd7b93a505f9a9@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19745
Logged by: Ke
Email address: kehan5800(at)gmail(dot)com
PostgreSQL version: 18.6
Operating system: Ubuntu 22.04.2 x86_64
Description:
makepol() in src/backend/utils/adt/tsquery.c keeps a fixed operator stack
(STACKDEPTH = 32, tsquery.c:627), and pushOpStack() reports overflow as an
internal error:
static void
pushOpStack(OperatorElement *stack, int *lenstack, int8 op, int16
distance)
{
if (*lenstack == STACKDEPTH) /* internal error */
elog(ERROR, "tsquery stack too small");
(tsquery.c:638-639). The prefix operator "!" pushes an entry per occurrence,
so the condition is reachable from plain user input:
SELECT (repeat('!', 32) || 'a')::tsquery; -- ok
SELECT (repeat('!', 33) || 'a')::tsquery;
ERROR: XX000: tsquery stack too small
LOCATION: pushOpStack, tsquery.c:639
SELECT websearch_to_tsquery('simple', repeat('-', 33) || 'a');
ERROR: XX000: tsquery stack too small
SELECT to_tsquery('simple', repeat('!', 33) || 'a');
ERROR: XX000: tsquery stack too small
Because this is elog() rather than ereturn(escontext, ...), it bypasses the
soft-error machinery used since 16:
SELECT pg_input_is_valid(repeat('!', 32) || 'a', 'tsquery'); -- t
SELECT pg_input_is_valid(repeat('!', 33) || 'a', 'tsquery');
ERROR: XX000: tsquery stack too small
and COPY ... (ON_ERROR ignore) aborts the whole load instead of skipping
the row:
CREATE TABLE onerr (q tsquery);
-- onerr.txt: a & b
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!a (33 "!")
-- c & d
\copy onerr from 'onerr.txt' (on_error ignore)
ERROR: XX000: tsquery stack too small
CONTEXT: COPY onerr, line 2, column q:
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!a"
SELECT count(*) FROM onerr; -- 0
Expected: an ordinary user-facing error with a proper SQLSTATE (e.g.
54001 statement_too_complex or 54000 program_limit_exceeded), raised through
the soft-error path so that pg_input_is_valid() returns false and
ON_ERROR ignore skips the row. websearch_to_tsquery() is documented for raw
user search input, so an XX000 from 33 hyphens typed into a search box is
the wrong category.
Actual: XX000 internal_error, not catchable by pg_input_is_valid() or
ON_ERROR ignore.
For comparison, intarray's copy of the same parser (contrib/intarray/
_int_bool.c:181-184) was converted when soft errors were introduced:
if (lenstack == STACKDEPTH)
ereturn(state->escontext, ERR,
(errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
errmsg("statement too complex")));
SELECT pg_input_is_valid(repeat('!', 17) || '1', 'query_int'); -- f
The third copy, contrib/ltree/ltxtquery_io.c:252 (elog(ERROR, "stack too
short")), behaves like tsquery: 33 stacked "!" give XX000 and
pg_input_is_valid(..., 'ltxtquery') raises. That one was noted earlier in
https://www.postgresql.org/message-id/749c63a4-ff67-76a8-e6d4-53b293931c81@gmail.com
Suggested fix: pass the TSQueryParserState to pushOpStack() and report the
overflow with errsave(state->escontext, ...) as intarray does (e.g.
ERRCODE_STATEMENT_TOO_COMPLEX, "tsquery is too complex", errdetail naming
the limit), then return; makepol() already checks
SOFT_ERROR_OCCURRED(state->escontext) after each token and returns, so no
other plumbing is needed. The same change applies to ltxtquery_io.c's
makepol().
Raising STACKDEPTH alone would not address the error class or the
soft-error escape.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | PG Bug reporting form | 2026-10-04 05:18:39 | BUG #19746: interval with INT64_MIN microseconds prints a value interval_in rejects |
| Previous Message | PG Bug reporting form | 2026-10-04 05:16:30 | BUG #19744: contrib/seg output truncates to 6 significant digits, breaking dump/restore |