Skip to content

Commit 680aabd

Browse files
committed
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
1 parent b99bfc3 commit 680aabd

File tree

3 files changed

+93
-3
lines changed

3 files changed

+93
-3
lines changed

src/backend/tsearch/spell.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,8 @@ IsAffixFlagInUse(IspellDict *Conf, int affix, char *affixflag)
458458
if (*affixflag == 0)
459459
return true;
460460

461+
Assert(affix < Conf->nAffixData);
462+
461463
flagcur = Conf->AffixData[affix];
462464

463465
while (*flagcur)
@@ -1160,13 +1162,17 @@ getAffixFlagSet(IspellDict *Conf, char *s)
11601162
(errcode(ERRCODE_CONFIG_FILE_ERROR),
11611163
errmsg("invalid affix alias \"%s\"", s)));
11621164

1163-
if (curaffix > 0 && curaffix <= Conf->nAffixData)
1165+
if (curaffix > 0 && curaffix < Conf->nAffixData)
11641166

11651167
/*
11661168
* Do not subtract 1 from curaffix because empty string was added
11671169
* in NIImportOOAffixes
11681170
*/
11691171
return Conf->AffixData[curaffix];
1172+
else if (curaffix > Conf->nAffixData)
1173+
ereport(ERROR,
1174+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
1175+
errmsg("invalid affix alias \"%s\"", s)));
11701176
else
11711177
return VoidString;
11721178
}
@@ -1556,6 +1562,8 @@ MergeAffix(IspellDict *Conf, int a1, int a2)
15561562
{
15571563
char **ptr;
15581564

1565+
Assert(a1 < Conf->nAffixData && a2 < Conf->nAffixData);
1566+
15591567
/* Do not merge affix flags if one of affix flags is empty */
15601568
if (*Conf->AffixData[a1] == '\0')
15611569
return a2;
@@ -1598,9 +1606,10 @@ MergeAffix(IspellDict *Conf, int a1, int a2)
15981606
static uint32
15991607
makeCompoundFlags(IspellDict *Conf, int affix)
16001608
{
1601-
char *str = Conf->AffixData[affix];
1609+
Assert(affix < Conf->nAffixData);
16021610

1603-
return (getCompoundAffixFlagValue(Conf, str) & FF_COMPOUNDFLAGMASK);
1611+
return (getCompoundAffixFlagValue(Conf, Conf->AffixData[affix]) &
1612+
FF_COMPOUNDFLAGMASK);
16041613
}
16051614

16061615
/*
@@ -1720,6 +1729,16 @@ NISortDictionary(IspellDict *Conf)
17201729
(errcode(ERRCODE_CONFIG_FILE_ERROR),
17211730
errmsg("invalid affix alias \"%s\"",
17221731
Conf->Spell[i]->p.flag)));
1732+
if (curaffix < 0 || curaffix >= Conf->nAffixData)
1733+
ereport(ERROR,
1734+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
1735+
errmsg("invalid affix alias \"%s\"",
1736+
Conf->Spell[i]->p.flag)));
1737+
if (*end != '\0' && !t_isdigit(end) && !t_isspace(end))
1738+
ereport(ERROR,
1739+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
1740+
errmsg("invalid affix alias \"%s\"",
1741+
Conf->Spell[i]->p.flag)));
17231742
}
17241743
else
17251744
{

src/test/regress/expected/tsdicts.out

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,40 @@ SELECT ts_lexize('hunspell_num', 'footballyklubber');
383383
{foot,ball,klubber}
384384
(1 row)
385385

386+
-- Test suitability of affix and dict files
387+
CREATE TEXT SEARCH DICTIONARY hunspell_err (
388+
Template=ispell,
389+
DictFile=ispell_sample,
390+
AffFile=hunspell_sample_long
391+
);
392+
ERROR: invalid affix alias "GJUS"
393+
CREATE TEXT SEARCH DICTIONARY hunspell_err (
394+
Template=ispell,
395+
DictFile=ispell_sample,
396+
AffFile=hunspell_sample_num
397+
);
398+
ERROR: invalid affix flag "SZ\"
399+
CREATE TEXT SEARCH DICTIONARY hunspell_invalid_1 (
400+
Template=ispell,
401+
DictFile=hunspell_sample_long,
402+
AffFile=ispell_sample
403+
);
404+
CREATE TEXT SEARCH DICTIONARY hunspell_invalid_2 (
405+
Template=ispell,
406+
DictFile=hunspell_sample_long,
407+
AffFile=hunspell_sample_num
408+
);
409+
CREATE TEXT SEARCH DICTIONARY hunspell_invalid_3 (
410+
Template=ispell,
411+
DictFile=hunspell_sample_num,
412+
AffFile=ispell_sample
413+
);
414+
CREATE TEXT SEARCH DICTIONARY hunspell_err (
415+
Template=ispell,
416+
DictFile=hunspell_sample_num,
417+
AffFile=hunspell_sample_long
418+
);
419+
ERROR: invalid affix alias "302,301,202,303"
386420
-- Synonym dictionary
387421
CREATE TEXT SEARCH DICTIONARY synonym (
388422
Template=synonym,

src/test/regress/sql/tsdicts.sql

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,43 @@ SELECT ts_lexize('hunspell_num', 'footballklubber');
9696
SELECT ts_lexize('hunspell_num', 'ballyklubber');
9797
SELECT ts_lexize('hunspell_num', 'footballyklubber');
9898

99+
-- Test suitability of affix and dict files
100+
CREATE TEXT SEARCH DICTIONARY hunspell_err (
101+
Template=ispell,
102+
DictFile=ispell_sample,
103+
AffFile=hunspell_sample_long
104+
);
105+
106+
CREATE TEXT SEARCH DICTIONARY hunspell_err (
107+
Template=ispell,
108+
DictFile=ispell_sample,
109+
AffFile=hunspell_sample_num
110+
);
111+
112+
CREATE TEXT SEARCH DICTIONARY hunspell_invalid_1 (
113+
Template=ispell,
114+
DictFile=hunspell_sample_long,
115+
AffFile=ispell_sample
116+
);
117+
118+
CREATE TEXT SEARCH DICTIONARY hunspell_invalid_2 (
119+
Template=ispell,
120+
DictFile=hunspell_sample_long,
121+
AffFile=hunspell_sample_num
122+
);
123+
124+
CREATE TEXT SEARCH DICTIONARY hunspell_invalid_3 (
125+
Template=ispell,
126+
DictFile=hunspell_sample_num,
127+
AffFile=ispell_sample
128+
);
129+
130+
CREATE TEXT SEARCH DICTIONARY hunspell_err (
131+
Template=ispell,
132+
DictFile=hunspell_sample_num,
133+
AffFile=hunspell_sample_long
134+
);
135+
99136
-- Synonym dictionary
100137
CREATE TEXT SEARCH DICTIONARY synonym (
101138
Template=synonym,

0 commit comments

Comments
 (0)