pg.ddx.io  pgsql-committers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files
7+ messages / 1 participants
[nested] [flat]

* pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files
@ 2026-08-30 00:12  Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 0 replies; 7+ messages in thread

From: Tom Lane @ 2026-08-30 00:12 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Harden spell.c against out-of-order FLAG lines in Hunspell files.

The compound flags collected from COMPOUNDFLAG and friends are stored in
either the string or the integer member of a union, according to the
flag mode that the affix file's FLAG line declares.  NIImportOOAffixes()
converted each flag as soon as it read it, using the mode in effect at
that point, and recorded that mode in the entry.  Since FLAG may appear
anywhere in the file, including after the compound flags, entries written
before and after it could disagree about which member of the union holds
the flag.

In assert-enabled builds, this would result in an assertion failure.
Otherwise, cmpcmdflag() takes the mode from its first argument and
applies it to both, so it can read an integer as a char pointer and pass
that to strcmp().  Depending on which way the mismatch goes, the result
is a segfault while sorting the array, a segfault in the bsearch() that
later looks flags up (the lookup key is built with the final mode, so
this happens even when the array itself is consistent), or, when both
members happen to be readable, no crash at all and a compound flag that
is never found, which silently disables compound word splitting.  This
isn't a security bug because we consider dictionary files to be trusted
data, but it's still worth fixing.  (In practice, dictionary files
usually put the FLAG line first, which is why this went unreported for
so long.)

Fix by keeping the flags as strings while the file is read and converting
them once it has been read in full, when the mode is final.  This also
makes the position of the FLAG line irrelevant, which is how the flags on
AF, SFX and PFX lines are already treated: those are parsed in a second
pass and so always use the final mode.  That precedent is reason for
behaving this way rather than throwing an error.

The old ispell file format reaches addCompoundAffixFlagValue() too,
from NIImportAffixes(), and returns without entering NIImportOOAffixes(),
so it needs the conversion step as well.

While we're here, also fix some integer width mismatches: store the
result of strtol() into a "long", and cast to int only after we've done
range checks.  Typically a value too wide for int would fail the range
checks anyway, but in some cases it would be silently accepted after
truncation to int.

Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAON2xHN3QmsaySM6DGWa1gttcbJoFh0wjAE-_ZpSPo=LKN1hYw@mail.gmail.com
Backpatch-through: 14

Branch
------
REL_17_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/e96b27296bec1c6212874eceb394b4f8b7d06dcc

Modified Files
--------------
src/backend/tsearch/spell.c | 115 +++++++++++++++++++++++++++++++++-----------
1 file changed, 88 insertions(+), 27 deletions(-)



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files
@ 2026-08-30 00:12  Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 0 replies; 7+ messages in thread

From: Tom Lane @ 2026-08-30 00:12 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Harden spell.c against out-of-order FLAG lines in Hunspell files.

The compound flags collected from COMPOUNDFLAG and friends are stored in
either the string or the integer member of a union, according to the
flag mode that the affix file's FLAG line declares.  NIImportOOAffixes()
converted each flag as soon as it read it, using the mode in effect at
that point, and recorded that mode in the entry.  Since FLAG may appear
anywhere in the file, including after the compound flags, entries written
before and after it could disagree about which member of the union holds
the flag.

In assert-enabled builds, this would result in an assertion failure.
Otherwise, cmpcmdflag() takes the mode from its first argument and
applies it to both, so it can read an integer as a char pointer and pass
that to strcmp().  Depending on which way the mismatch goes, the result
is a segfault while sorting the array, a segfault in the bsearch() that
later looks flags up (the lookup key is built with the final mode, so
this happens even when the array itself is consistent), or, when both
members happen to be readable, no crash at all and a compound flag that
is never found, which silently disables compound word splitting.  This
isn't a security bug because we consider dictionary files to be trusted
data, but it's still worth fixing.  (In practice, dictionary files
usually put the FLAG line first, which is why this went unreported for
so long.)

Fix by keeping the flags as strings while the file is read and converting
them once it has been read in full, when the mode is final.  This also
makes the position of the FLAG line irrelevant, which is how the flags on
AF, SFX and PFX lines are already treated: those are parsed in a second
pass and so always use the final mode.  That precedent is reason for
behaving this way rather than throwing an error.

The old ispell file format reaches addCompoundAffixFlagValue() too,
from NIImportAffixes(), and returns without entering NIImportOOAffixes(),
so it needs the conversion step as well.

While we're here, also fix some integer width mismatches: store the
result of strtol() into a "long", and cast to int only after we've done
range checks.  Typically a value too wide for int would fail the range
checks anyway, but in some cases it would be silently accepted after
truncation to int.

Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAON2xHN3QmsaySM6DGWa1gttcbJoFh0wjAE-_ZpSPo=LKN1hYw@mail.gmail.com
Backpatch-through: 14

Branch
------
REL_14_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/b4c8afdfaf52ce4a5839be6b4d205e696b00a543

Modified Files
--------------
src/backend/tsearch/spell.c | 115 +++++++++++++++++++++++++++++++++-----------
1 file changed, 88 insertions(+), 27 deletions(-)



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files
@ 2026-08-30 00:12  Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 0 replies; 7+ messages in thread

From: Tom Lane @ 2026-08-30 00:12 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Harden spell.c against out-of-order FLAG lines in Hunspell files.

The compound flags collected from COMPOUNDFLAG and friends are stored in
either the string or the integer member of a union, according to the
flag mode that the affix file's FLAG line declares.  NIImportOOAffixes()
converted each flag as soon as it read it, using the mode in effect at
that point, and recorded that mode in the entry.  Since FLAG may appear
anywhere in the file, including after the compound flags, entries written
before and after it could disagree about which member of the union holds
the flag.

In assert-enabled builds, this would result in an assertion failure.
Otherwise, cmpcmdflag() takes the mode from its first argument and
applies it to both, so it can read an integer as a char pointer and pass
that to strcmp().  Depending on which way the mismatch goes, the result
is a segfault while sorting the array, a segfault in the bsearch() that
later looks flags up (the lookup key is built with the final mode, so
this happens even when the array itself is consistent), or, when both
members happen to be readable, no crash at all and a compound flag that
is never found, which silently disables compound word splitting.  This
isn't a security bug because we consider dictionary files to be trusted
data, but it's still worth fixing.  (In practice, dictionary files
usually put the FLAG line first, which is why this went unreported for
so long.)

Fix by keeping the flags as strings while the file is read and converting
them once it has been read in full, when the mode is final.  This also
makes the position of the FLAG line irrelevant, which is how the flags on
AF, SFX and PFX lines are already treated: those are parsed in a second
pass and so always use the final mode.  That precedent is reason for
behaving this way rather than throwing an error.

The old ispell file format reaches addCompoundAffixFlagValue() too,
from NIImportAffixes(), and returns without entering NIImportOOAffixes(),
so it needs the conversion step as well.

While we're here, also fix some integer width mismatches: store the
result of strtol() into a "long", and cast to int only after we've done
range checks.  Typically a value too wide for int would fail the range
checks anyway, but in some cases it would be silently accepted after
truncation to int.

Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAON2xHN3QmsaySM6DGWa1gttcbJoFh0wjAE-_ZpSPo=LKN1hYw@mail.gmail.com
Backpatch-through: 14

Branch
------
REL_15_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/1eca8b94d7aae6c10904c1adda62effebd5539fc

Modified Files
--------------
src/backend/tsearch/spell.c | 115 +++++++++++++++++++++++++++++++++-----------
1 file changed, 88 insertions(+), 27 deletions(-)



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files
@ 2026-08-30 00:12  Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 0 replies; 7+ messages in thread

From: Tom Lane @ 2026-08-30 00:12 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Harden spell.c against out-of-order FLAG lines in Hunspell files.

The compound flags collected from COMPOUNDFLAG and friends are stored in
either the string or the integer member of a union, according to the
flag mode that the affix file's FLAG line declares.  NIImportOOAffixes()
converted each flag as soon as it read it, using the mode in effect at
that point, and recorded that mode in the entry.  Since FLAG may appear
anywhere in the file, including after the compound flags, entries written
before and after it could disagree about which member of the union holds
the flag.

In assert-enabled builds, this would result in an assertion failure.
Otherwise, cmpcmdflag() takes the mode from its first argument and
applies it to both, so it can read an integer as a char pointer and pass
that to strcmp().  Depending on which way the mismatch goes, the result
is a segfault while sorting the array, a segfault in the bsearch() that
later looks flags up (the lookup key is built with the final mode, so
this happens even when the array itself is consistent), or, when both
members happen to be readable, no crash at all and a compound flag that
is never found, which silently disables compound word splitting.  This
isn't a security bug because we consider dictionary files to be trusted
data, but it's still worth fixing.  (In practice, dictionary files
usually put the FLAG line first, which is why this went unreported for
so long.)

Fix by keeping the flags as strings while the file is read and converting
them once it has been read in full, when the mode is final.  This also
makes the position of the FLAG line irrelevant, which is how the flags on
AF, SFX and PFX lines are already treated: those are parsed in a second
pass and so always use the final mode.  That precedent is reason for
behaving this way rather than throwing an error.

The old ispell file format reaches addCompoundAffixFlagValue() too,
from NIImportAffixes(), and returns without entering NIImportOOAffixes(),
so it needs the conversion step as well.

While we're here, also fix some integer width mismatches: store the
result of strtol() into a "long", and cast to int only after we've done
range checks.  Typically a value too wide for int would fail the range
checks anyway, but in some cases it would be silently accepted after
truncation to int.

Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAON2xHN3QmsaySM6DGWa1gttcbJoFh0wjAE-_ZpSPo=LKN1hYw@mail.gmail.com
Backpatch-through: 14

Branch
------
REL_18_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/1f02a1e488f7b0f4c962a19d6b7b8e172f97d9c2

Modified Files
--------------
src/backend/tsearch/spell.c | 115 +++++++++++++++++++++++++++++++++-----------
1 file changed, 88 insertions(+), 27 deletions(-)



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files
@ 2026-08-30 00:12  Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 0 replies; 7+ messages in thread

From: Tom Lane @ 2026-08-30 00:12 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Harden spell.c against out-of-order FLAG lines in Hunspell files.

The compound flags collected from COMPOUNDFLAG and friends are stored in
either the string or the integer member of a union, according to the
flag mode that the affix file's FLAG line declares.  NIImportOOAffixes()
converted each flag as soon as it read it, using the mode in effect at
that point, and recorded that mode in the entry.  Since FLAG may appear
anywhere in the file, including after the compound flags, entries written
before and after it could disagree about which member of the union holds
the flag.

In assert-enabled builds, this would result in an assertion failure.
Otherwise, cmpcmdflag() takes the mode from its first argument and
applies it to both, so it can read an integer as a char pointer and pass
that to strcmp().  Depending on which way the mismatch goes, the result
is a segfault while sorting the array, a segfault in the bsearch() that
later looks flags up (the lookup key is built with the final mode, so
this happens even when the array itself is consistent), or, when both
members happen to be readable, no crash at all and a compound flag that
is never found, which silently disables compound word splitting.  This
isn't a security bug because we consider dictionary files to be trusted
data, but it's still worth fixing.  (In practice, dictionary files
usually put the FLAG line first, which is why this went unreported for
so long.)

Fix by keeping the flags as strings while the file is read and converting
them once it has been read in full, when the mode is final.  This also
makes the position of the FLAG line irrelevant, which is how the flags on
AF, SFX and PFX lines are already treated: those are parsed in a second
pass and so always use the final mode.  That precedent is reason for
behaving this way rather than throwing an error.

The old ispell file format reaches addCompoundAffixFlagValue() too,
from NIImportAffixes(), and returns without entering NIImportOOAffixes(),
so it needs the conversion step as well.

While we're here, also fix some integer width mismatches: store the
result of strtol() into a "long", and cast to int only after we've done
range checks.  Typically a value too wide for int would fail the range
checks anyway, but in some cases it would be silently accepted after
truncation to int.

Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAON2xHN3QmsaySM6DGWa1gttcbJoFh0wjAE-_ZpSPo=LKN1hYw@mail.gmail.com
Backpatch-through: 14

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/15ee73d7d7cd6bf01ba721603067fa59be746b3c

Modified Files
--------------
src/backend/tsearch/spell.c | 115 +++++++++++++++++++++++++++++++++-----------
1 file changed, 88 insertions(+), 27 deletions(-)



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files
@ 2026-08-30 00:12  Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 0 replies; 7+ messages in thread

From: Tom Lane @ 2026-08-30 00:12 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Harden spell.c against out-of-order FLAG lines in Hunspell files.

The compound flags collected from COMPOUNDFLAG and friends are stored in
either the string or the integer member of a union, according to the
flag mode that the affix file's FLAG line declares.  NIImportOOAffixes()
converted each flag as soon as it read it, using the mode in effect at
that point, and recorded that mode in the entry.  Since FLAG may appear
anywhere in the file, including after the compound flags, entries written
before and after it could disagree about which member of the union holds
the flag.

In assert-enabled builds, this would result in an assertion failure.
Otherwise, cmpcmdflag() takes the mode from its first argument and
applies it to both, so it can read an integer as a char pointer and pass
that to strcmp().  Depending on which way the mismatch goes, the result
is a segfault while sorting the array, a segfault in the bsearch() that
later looks flags up (the lookup key is built with the final mode, so
this happens even when the array itself is consistent), or, when both
members happen to be readable, no crash at all and a compound flag that
is never found, which silently disables compound word splitting.  This
isn't a security bug because we consider dictionary files to be trusted
data, but it's still worth fixing.  (In practice, dictionary files
usually put the FLAG line first, which is why this went unreported for
so long.)

Fix by keeping the flags as strings while the file is read and converting
them once it has been read in full, when the mode is final.  This also
makes the position of the FLAG line irrelevant, which is how the flags on
AF, SFX and PFX lines are already treated: those are parsed in a second
pass and so always use the final mode.  That precedent is reason for
behaving this way rather than throwing an error.

The old ispell file format reaches addCompoundAffixFlagValue() too,
from NIImportAffixes(), and returns without entering NIImportOOAffixes(),
so it needs the conversion step as well.

While we're here, also fix some integer width mismatches: store the
result of strtol() into a "long", and cast to int only after we've done
range checks.  Typically a value too wide for int would fail the range
checks anyway, but in some cases it would be silently accepted after
truncation to int.

Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAON2xHN3QmsaySM6DGWa1gttcbJoFh0wjAE-_ZpSPo=LKN1hYw@mail.gmail.com
Backpatch-through: 14

Branch
------
REL_19_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/50daffb0665e31ba9e223e3c9106a49f2c44eab5

Modified Files
--------------
src/backend/tsearch/spell.c | 115 +++++++++++++++++++++++++++++++++-----------
1 file changed, 88 insertions(+), 27 deletions(-)



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files
@ 2026-08-30 00:12  Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 0 replies; 7+ messages in thread

From: Tom Lane @ 2026-08-30 00:12 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Harden spell.c against out-of-order FLAG lines in Hunspell files.

The compound flags collected from COMPOUNDFLAG and friends are stored in
either the string or the integer member of a union, according to the
flag mode that the affix file's FLAG line declares.  NIImportOOAffixes()
converted each flag as soon as it read it, using the mode in effect at
that point, and recorded that mode in the entry.  Since FLAG may appear
anywhere in the file, including after the compound flags, entries written
before and after it could disagree about which member of the union holds
the flag.

In assert-enabled builds, this would result in an assertion failure.
Otherwise, cmpcmdflag() takes the mode from its first argument and
applies it to both, so it can read an integer as a char pointer and pass
that to strcmp().  Depending on which way the mismatch goes, the result
is a segfault while sorting the array, a segfault in the bsearch() that
later looks flags up (the lookup key is built with the final mode, so
this happens even when the array itself is consistent), or, when both
members happen to be readable, no crash at all and a compound flag that
is never found, which silently disables compound word splitting.  This
isn't a security bug because we consider dictionary files to be trusted
data, but it's still worth fixing.  (In practice, dictionary files
usually put the FLAG line first, which is why this went unreported for
so long.)

Fix by keeping the flags as strings while the file is read and converting
them once it has been read in full, when the mode is final.  This also
makes the position of the FLAG line irrelevant, which is how the flags on
AF, SFX and PFX lines are already treated: those are parsed in a second
pass and so always use the final mode.  That precedent is reason for
behaving this way rather than throwing an error.

The old ispell file format reaches addCompoundAffixFlagValue() too,
from NIImportAffixes(), and returns without entering NIImportOOAffixes(),
so it needs the conversion step as well.

While we're here, also fix some integer width mismatches: store the
result of strtol() into a "long", and cast to int only after we've done
range checks.  Typically a value too wide for int would fail the range
checks anyway, but in some cases it would be silently accepted after
truncation to int.

Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAON2xHN3QmsaySM6DGWa1gttcbJoFh0wjAE-_ZpSPo=LKN1hYw@mail.gmail.com
Backpatch-through: 14

Branch
------
REL_16_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/5827ddfc27226a948f60b4c08c6aa405e81d5f74

Modified Files
--------------
src/backend/tsearch/spell.c | 115 +++++++++++++++++++++++++++++++++-----------
1 file changed, 88 insertions(+), 27 deletions(-)



^ permalink  raw  reply  [nested|flat] 7+ messages in thread


end of thread, other threads:[~2026-08-30 00:12 UTC | newest]

Thread overview: 7+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-08-30 00:12 pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files Tom Lane <tgl@sss.pgh.pa.us>
2026-08-30 00:12 pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files Tom Lane <tgl@sss.pgh.pa.us>
2026-08-30 00:12 pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files Tom Lane <tgl@sss.pgh.pa.us>
2026-08-30 00:12 pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files Tom Lane <tgl@sss.pgh.pa.us>
2026-08-30 00:12 pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files Tom Lane <tgl@sss.pgh.pa.us>
2026-08-30 00:12 pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files Tom Lane <tgl@sss.pgh.pa.us>
2026-08-30 00:12 pgsql: Harden spell.c against out-of-order FLAG lines in Hunspell files Tom Lane <tgl@sss.pgh.pa.us>

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox