agora inbox for pgsql-bugs@postgresql.org  
help / color / mirror / Atom feed
From: 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