Hunspell AF alias count silently wraps to a smaller value

Started by ♂π≌2621812 days ago2 messagesbugs
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

appliestests failedCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253742
psql -h localhost -U postgres

Built from patchset v2 (message #2), September 20, 2026 at 03:05 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253742_2 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253742_2 && git checkout t253742_2

Patchset v2 (message #2) is on t253742_2

Jump to latest
#1♂π≌26218
1991230470@qq.com

Hi, I found a potential bug in PostgreSQL's Hunspell dictionary parser where an over-wide `AF` alias count in an affix file is accepted after being silently converted to a smaller positive integer, without any error or warning. Description: An affix file declaring `AF 4294967297` (which exceeds the maximum value representable in a 32-bit unsigned integer by 1) but containing only one alias definition loads successfully and behaves as if it declared one alias. The parsing path appears to use a narrow integer conversion and validates only the converted value, not whether the original number can be represented without loss. PostgreSQL version: - PostgreSQL 19beta3 (Docker-based runtime) - Source commit: not recorded in the original report - Build relationship: the tested image was not an exact-HEAD build Environment: - Docker-based PostgreSQL 19beta3 runtime - Hunspell dictionary support enabled by default - No special server configuration required beyond superuser access to create dictionaries Steps to Reproduce: Create `af_overflow.affix` in PostgreSQL's `tsearch_data` directory: ```text SET UTF-8 AF 4294967297 AF A PFX A Y 1 PFX A 0 re .

Create af_overflow.dict:
text

book/1

Then, as a superuser, execute the following SQL:
sql

\set VERBOSITY verbose CREATE TEXT SEARCH DICTIONARY af_overflow (  TEMPLATE = ispell,  DictFile = af_overflow,  AffFile = af_overflow ); SELECT ts_lexize('af_overflow', 'rebook');

Actual Result:

The dictionary is created successfully without any error. ts_lexize returns:
text

{book}

The declared value 4294967297 effectively behaves as if the alias count was 1, which matches the number of defined aliases.

Expected Result:

The loader should reject an AF count that is out of range, cannot be converted losslessly, or does not match the number of alias definitions. An explicit error message such as "AF alias count out of range" or "number of AF aliases does not match declaration" would be appropriate.

Reproduction Frequency:

Positive reproduction: 2/2 on PostgreSQL 19beta3

Negative control: replacing the count with AF 1 loads and lexizes normally

Additional Observations:

This appears to be a low-impact issue because it requires elevated privileges to install dictionary files and create text-search dictionaries. However, it could lead to subtle misbehavior if a dictionary file with an overflowed count is accidentally used. The issue is likely located in the affix-file parsing code where the AF count is converted without checking for overflow or loss of precision.

I searched the public PostgreSQL bug archives and did not find any report specifically addressing overflow handling of AF alias counts. Please confirm whether this is considered a bug or an intentional limitation of the parsing logic.

♂π≌26218
1991230470@qq.com

#2Andrey Rachitskiy
pl0h0yp1@gmail.com
In reply to: ♂π≌26218 (#1)
Re: Hunspell AF alias count silently wraps to a smaller value

чт, 10 сент. 2026 г. в 17:08, ♂π≌26218 <1991230470@qq.com>:

Hi,

I found a potential bug in PostgreSQL's Hunspell dictionary parser where an over-wide `AF` alias count in an affix file is accepted after being silently converted to a smaller positive integer, without any error or warning.

Description:

An affix file declaring `AF 4294967297` (which exceeds the maximum value representable in a 32-bit unsigned integer by 1) but containing only one alias definition loads successfully and behaves as if it declared one alias. The parsing path appears to use a narrow integer conversion and validates only the converted value, not whether the original number can be represented without loss.

PostgreSQL version:
- PostgreSQL 19beta3 (Docker-based runtime)
- Source commit: not recorded in the original report
- Build relationship: the tested image was not an exact-HEAD build

Environment:
- Docker-based PostgreSQL 19beta3 runtime
- Hunspell dictionary support enabled by default
- No special server configuration required beyond superuser access to create dictionaries

Steps to Reproduce:

Create `af_overflow.affix` in PostgreSQL's `tsearch_data` directory:

```text
SET UTF-8
AF 4294967297
AF A
PFX A Y 1
PFX A 0 re .

Create af_overflow.dict:
text

book/1

Then, as a superuser, execute the following SQL:
sql

\set VERBOSITY verboseCREATE TEXT SEARCH DICTIONARY af_overflow (
TEMPLATE = ispell,
DictFile = af_overflow,
AffFile = af_overflow);SELECT ts_lexize('af_overflow', 'rebook');

Actual Result:

The dictionary is created successfully without any error. ts_lexize
returns:
text

{book}

The declared value 4294967297 effectively behaves as if the alias count
was 1, which matches the number of defined aliases.

Expected Result:

The loader should reject an AF count that is out of range, cannot be
converted losslessly, or does not match the number of alias definitions. An
explicit error message such as "AF alias count out of range" or "number of
AF aliases does not match declaration" would be appropriate.

Reproduction Frequency:

-

Positive reproduction: 2/2 on PostgreSQL 19beta3
-

Negative control: replacing the count with AF 1 loads and lexizes
normally

Additional Observations:

This appears to be a low-impact issue because it requires elevated
privileges to install dictionary files and create text-search dictionaries.
However, it could lead to subtle misbehavior if a dictionary file with an
overflowed count is accidentally used. The issue is likely located in the
affix-file parsing code where the AF count is converted without checking
for overflow or loss of precision.

I searched the public PostgreSQL bug archives and did not find any report
specifically addressing overflow handling of AF alias counts. Please
confirm whether this is considered a bug or an intentional limitation of
the parsing logic.

♂π≌26218
1991230470@qq.com

<https://wx.mail.qq.com/home/index?t=readmail_businesscard_midpage&amp;nocheck=true&amp;name=%E2%99%82%CF%80%E2%89%8C26218&amp;icon=https%3A%2F%2Fp.qlogo.cn%2Fqqmail_head%2F7zCZdnCEqwFr60hzEibU1KOjLPppnhmolM05y60o9OJhh4GoeKYHtrSgNUk8KpD2I%2F160&amp;mail=1991230470%40qq.com&amp;code=g5VzPQl67UBOaO3N0VLdCtumeljBoBFYOGmy5Le_CPM8hp3rB1CbWb9Mf7UfBsq8Ecxg9ZBK8rZhZfvlSXXlwg&gt;

Hi!

Thnx for the report.

Proposal Fix
-----------------
Parse the count with strtol(), same pattern as parseNumericAffixFlag().
Reject ERANGE, non-numeric input, n <= 0, and n >= INT_MAX (room is
needed for the empty flag-set slot).

--
Regards,
Rachitskiy Andrey

Attachments:

t253742_2
0001-Reject-out-of-range-Hunspell-AF-alias-counts.patchtext/x-patch; charset=US-ASCII; name=0001-Reject-out-of-range-Hunspell-AF-alias-counts.patchDownload+31-4