]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Validate ispell dictionaries more carefully.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 2 Nov 2019 20:45:32 +0000 (16:45 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 2 Nov 2019 20:45:32 +0000 (16:45 -0400)
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

src/backend/tsearch/spell.c
src/test/regress/expected/tsdicts.out
src/test/regress/sql/tsdicts.sql

index df28b270e1de9751a4643e18554e23a7cd9a0ba0..57f24d16613d28a0e758d4bced400e321103d9cd 100644 (file)
@@ -458,6 +458,8 @@ IsAffixFlagInUse(IspellDict *Conf, int affix, 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;
        }
@@ -1556,6 +1562,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;
@@ -1598,9 +1606,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);
 }
 
 /*
@@ -1720,6 +1729,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
                        {
index 0744ef803b1c95157f3d1424c267acaaec05474d..eed0d538d0529dca0ee1451c88832087cacb2160 100644 (file)
@@ -383,6 +383,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,
index a5a569e1ad4f21e5b13ae33662fd1884163561aa..ed8e2578c558d727035c20499d1b403c85906e06 100644 (file)
@@ -96,6 +96,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,