diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-11-02 16:45:32 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-11-02 16:45:32 -0400 |
commit | 43753c2cfbdd9870e68671abcc9dd377881071b0 (patch) | |
tree | 10f862217b6621ad94015607fbc1bf847ed5c801 /src | |
parent | 7963c4c4b7821f286e335c8aed66821c87404ce3 (diff) | |
download | postgresql-43753c2cfbdd9870e68671abcc9dd377881071b0.tar.gz postgresql-43753c2cfbdd9870e68671abcc9dd377881071b0.zip |
Validate ispell dictionaries more carefully.
Using incorrect, or just mismatched, dictionary and affix files
could result in a crash, due to failure to cross-check offsets
obtained from the file. Add necessary validation, as well as
some Asserts for future-proofing.
Per bug #16050 from Alexander Lakhin. Back-patch to 9.6 where the
problem was introduced.
Arthur Zakirov, per initial investigation by Tomas Vondra
Discussion: https://postgr.es/m/16050-024ae722464ab604@postgresql.org
Discussion: https://postgr.es/m/20191013012610.2p2fp3zzpoav7jzf@development
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/tsearch/spell.c | 25 | ||||
-rw-r--r-- | src/test/regress/expected/tsdicts.out | 34 | ||||
-rw-r--r-- | src/test/regress/sql/tsdicts.sql | 37 |
3 files changed, 93 insertions, 3 deletions
diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c index c715f06b8e2..1b8766659c4 100644 --- a/src/backend/tsearch/spell.c +++ b/src/backend/tsearch/spell.c @@ -458,6 +458,8 @@ IsAffixFlagInUse(IspellDict *Conf, int affix, const char *affixflag) if (*affixflag == 0) return true; + Assert(affix < Conf->nAffixData); + flagcur = Conf->AffixData[affix]; while (*flagcur) @@ -1160,13 +1162,17 @@ getAffixFlagSet(IspellDict *Conf, char *s) (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("invalid affix alias \"%s\"", s))); - if (curaffix > 0 && curaffix <= Conf->nAffixData) + if (curaffix > 0 && curaffix < Conf->nAffixData) /* * Do not subtract 1 from curaffix because empty string was added * in NIImportOOAffixes */ return Conf->AffixData[curaffix]; + else if (curaffix > Conf->nAffixData) + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("invalid affix alias \"%s\"", s))); else return VoidString; } @@ -1561,6 +1567,8 @@ MergeAffix(IspellDict *Conf, int a1, int a2) { char **ptr; + Assert(a1 < Conf->nAffixData && a2 < Conf->nAffixData); + /* Do not merge affix flags if one of affix flags is empty */ if (*Conf->AffixData[a1] == '\0') return a2; @@ -1603,9 +1611,10 @@ MergeAffix(IspellDict *Conf, int a1, int a2) static uint32 makeCompoundFlags(IspellDict *Conf, int affix) { - char *str = Conf->AffixData[affix]; + Assert(affix < Conf->nAffixData); - return (getCompoundAffixFlagValue(Conf, str) & FF_COMPOUNDFLAGMASK); + return (getCompoundAffixFlagValue(Conf, Conf->AffixData[affix]) & + FF_COMPOUNDFLAGMASK); } /* @@ -1725,6 +1734,16 @@ NISortDictionary(IspellDict *Conf) (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("invalid affix alias \"%s\"", Conf->Spell[i]->p.flag))); + if (curaffix < 0 || curaffix >= Conf->nAffixData) + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("invalid affix alias \"%s\"", + Conf->Spell[i]->p.flag))); + if (*end != '\0' && !t_isdigit(end) && !t_isspace(end)) + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("invalid affix alias \"%s\"", + Conf->Spell[i]->p.flag))); } else { diff --git a/src/test/regress/expected/tsdicts.out b/src/test/regress/expected/tsdicts.out index 2524ec2768f..5a927be9485 100644 --- a/src/test/regress/expected/tsdicts.out +++ b/src/test/regress/expected/tsdicts.out @@ -413,6 +413,40 @@ SELECT ts_lexize('hunspell_num', 'footballyklubber'); {foot,ball,klubber} (1 row) +-- Test suitability of affix and dict files +CREATE TEXT SEARCH DICTIONARY hunspell_err ( + Template=ispell, + DictFile=ispell_sample, + AffFile=hunspell_sample_long +); +ERROR: invalid affix alias "GJUS" +CREATE TEXT SEARCH DICTIONARY hunspell_err ( + Template=ispell, + DictFile=ispell_sample, + AffFile=hunspell_sample_num +); +ERROR: invalid affix flag "SZ\" +CREATE TEXT SEARCH DICTIONARY hunspell_invalid_1 ( + Template=ispell, + DictFile=hunspell_sample_long, + AffFile=ispell_sample +); +CREATE TEXT SEARCH DICTIONARY hunspell_invalid_2 ( + Template=ispell, + DictFile=hunspell_sample_long, + AffFile=hunspell_sample_num +); +CREATE TEXT SEARCH DICTIONARY hunspell_invalid_3 ( + Template=ispell, + DictFile=hunspell_sample_num, + AffFile=ispell_sample +); +CREATE TEXT SEARCH DICTIONARY hunspell_err ( + Template=ispell, + DictFile=hunspell_sample_num, + AffFile=hunspell_sample_long +); +ERROR: invalid affix alias "302,301,202,303" -- Synonym dictionary CREATE TEXT SEARCH DICTIONARY synonym ( Template=synonym, diff --git a/src/test/regress/sql/tsdicts.sql b/src/test/regress/sql/tsdicts.sql index 60906f6549a..908e6755018 100644 --- a/src/test/regress/sql/tsdicts.sql +++ b/src/test/regress/sql/tsdicts.sql @@ -101,6 +101,43 @@ SELECT ts_lexize('hunspell_num', 'footballklubber'); SELECT ts_lexize('hunspell_num', 'ballyklubber'); SELECT ts_lexize('hunspell_num', 'footballyklubber'); +-- Test suitability of affix and dict files +CREATE TEXT SEARCH DICTIONARY hunspell_err ( + Template=ispell, + DictFile=ispell_sample, + AffFile=hunspell_sample_long +); + +CREATE TEXT SEARCH DICTIONARY hunspell_err ( + Template=ispell, + DictFile=ispell_sample, + AffFile=hunspell_sample_num +); + +CREATE TEXT SEARCH DICTIONARY hunspell_invalid_1 ( + Template=ispell, + DictFile=hunspell_sample_long, + AffFile=ispell_sample +); + +CREATE TEXT SEARCH DICTIONARY hunspell_invalid_2 ( + Template=ispell, + DictFile=hunspell_sample_long, + AffFile=hunspell_sample_num +); + +CREATE TEXT SEARCH DICTIONARY hunspell_invalid_3 ( + Template=ispell, + DictFile=hunspell_sample_num, + AffFile=ispell_sample +); + +CREATE TEXT SEARCH DICTIONARY hunspell_err ( + Template=ispell, + DictFile=hunspell_sample_num, + AffFile=hunspell_sample_long +); + -- Synonym dictionary CREATE TEXT SEARCH DICTIONARY synonym ( Template=synonym, |