agora inbox for pgsql-bugs@postgresql.org
help / color / mirror / Atom feedFrom: PG Bug reporting form <noreply@postgresql.org>
To: pgsql-bugs@lists.postgresql.org
Cc: 1950233439@qq.com
Subject: BUG #19678: int16 Overflow in tsquery Phrase Distance After Stopword Removal
Date: Mon, 07 Sep 2026 14:21:21 +0000
Message-ID: <19678-790bf8888cef8cb5@postgresql.org> (raw)
The following bug has been logged on the website:
Bug reference: 19678
Logged by: Tianyu Shi
Email address: 1950233439@qq.com
PostgreSQL version: 19beta3
Operating system: Ubuntu22.04
Description:
### Summary
In `clean_stopword_intree()` (`src/backend/utils/adt/tsquery_cleanup.c`,
line 344), when a stopword is removed from between two `OP_PHRASE`
operators, the child operator's accumulated distance is added back to the
surviving parent via `node->valnode->qoperator.distance += lradd + rladd;`.
Because `qoperator.distance` is `int16`, the addition overflows silently
when the combined distances exceed INT16_MAX (32767). With two operators
each at the maximum valid input distance of 16384, the sum 32768 wraps to
−32768, producing a tsquery with a negative phrase distance. The corrupted
tsquery causes `TS_phrase_execute()` to emit silent false negatives —
documents that genuinely satisfy the phrase query are not returned — which
can subvert keyword-based security filters or content-gating logic without
raising any error.
### PoC
Reproducible by any user with the default PUBLIC privilege to call
`to_tsquery()`; no superuser or special role required.
```sql
-- Connect to any database
-- ./build/bin/psql -h ./build/run -p 55433 -U postgres postgres
-- Step 1: Observe the corrupted tsquery (distance becomes negative due to
int16 overflow)
SELECT to_tsquery('english', 'cat <16384> the <16384> dog') AS
corrupted_query;
-- Expected: 'cat' <32768> 'dog' (or a valid large distance)
-- Actual: 'cat' <-32768> 'dog' (int16 overflow: 16384+16384=32768 wraps
to -32768)
-- Step 2: Confirm false negative — the document contains both words but the
match fails
SELECT
to_tsvector('english', 'cat the dog')
@@
to_tsquery('english', 'cat <16384> the <16384> dog') AS matches;
-- Expected: t
-- Actual: f (false negative caused by corrupted negative distance)
-- Step 3: Sanity check — small positive distance still works
SELECT
to_tsvector('english', 'cat the dog')
@@
to_tsquery('english', 'cat <2> dog') AS sanity;
-- Expected and actual: t
```
### Result
`to_tsquery('english', 'cat <16384> the <16384> dog')` returns a tsquery
with a negative phrase distance instead of the mathematically correct
positive value:
```
corrupted_query
----------------------
'cat' <-32768> 'dog'
```
The corrupted distance causes a false negative in phrase matching:
```
matches_large_distance
------------------------
f
```
where `t` is expected (both words are present in the document). The overflow
is confirmed by extracting the distance directly:
```
actual_distance | mathematically_correct_distance | analysis
-----------------+---------------------------------+----------------------------------------------
-32768 | 32768 | BUG: distance is
negative, expected positive.
| | int16 overflow
confirmed.
```
No error or warning is emitted; the corrupted tsquery is silently accepted
and stored as a valid datum, making the failure invisible to callers.
Message-ID: <19678-790bf8888cef8cb5@postgresql.org>
Permalink: ../19678-790bf8888cef8cb5@postgresql.org/
Also on: postgresql.org/message-id/19678-790bf8888cef8cb5@postgresql.org
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-bugs@postgresql.org
Cc: noreply@postgresql.org, pgsql-bugs@lists.postgresql.org, 1950233439@qq.com
Subject: Re: BUG #19678: int16 Overflow in tsquery Phrase Distance After Stopword Removal
In-Reply-To: <19678-790bf8888cef8cb5@postgresql.org>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox