Commit b34d6f03 authored by Tom Lane's avatar Tom Lane

Improve ispell dictionary's defenses against bad affix files.

Don't crash if an ispell dictionary definition contains flags but not
any compound affixes.  (This isn't a security issue since only superusers
can install affix files, but still it's a bad thing.)

Also, be more careful about detecting whether an affix-file FLAG command
is old-format (ispell) or new-format (myspell/hunspell).  And change the
error message about mixed old-format and new-format commands into something
intelligible.

Per bug #11770 from Emre Hasegeli.  Back-patch to all supported branches.
parent 2781b4be
...@@ -599,6 +599,9 @@ addFlagValue(IspellDict *Conf, char *s, uint32 val) ...@@ -599,6 +599,9 @@ addFlagValue(IspellDict *Conf, char *s, uint32 val)
Conf->usecompound = true; Conf->usecompound = true;
} }
/*
* Import an affix file that follows MySpell or Hunspell format
*/
static void static void
NIImportOOAffixes(IspellDict *Conf, const char *filename) NIImportOOAffixes(IspellDict *Conf, const char *filename)
{ {
...@@ -757,6 +760,10 @@ nextline: ...@@ -757,6 +760,10 @@ nextline:
* import affixes * import affixes
* *
* Note caller must already have applied get_tsearch_config_filename * Note caller must already have applied get_tsearch_config_filename
*
* This function is responsible for parsing ispell ("old format") affix files.
* If we realize that the file contains new-format commands, we pass off the
* work to NIImportOOAffixes(), which will re-read the whole file.
*/ */
void void
NIImportAffixes(IspellDict *Conf, const char *filename) NIImportAffixes(IspellDict *Conf, const char *filename)
...@@ -833,13 +840,6 @@ NIImportAffixes(IspellDict *Conf, const char *filename) ...@@ -833,13 +840,6 @@ NIImportAffixes(IspellDict *Conf, const char *filename)
while (*s && t_isspace(s)) while (*s && t_isspace(s))
s += pg_mblen(s); s += pg_mblen(s);
oldformat = true;
/* allow only single-encoded flags */
if (pg_mblen(s) != 1)
ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("multibyte flag character is not allowed")));
if (*s == '*') if (*s == '*')
{ {
...@@ -855,26 +855,30 @@ NIImportAffixes(IspellDict *Conf, const char *filename) ...@@ -855,26 +855,30 @@ NIImportAffixes(IspellDict *Conf, const char *filename)
if (*s == '\\') if (*s == '\\')
s++; s++;
/* allow only single-encoded flags */ /*
if (pg_mblen(s) != 1) * An old-format flag is a single ASCII character; we expect it to
ereport(ERROR, * be followed by EOL, whitespace, or ':'. Otherwise this is a
(errcode(ERRCODE_CONFIG_FILE_ERROR), * new-format flag command.
errmsg("multibyte flag character is not allowed"))); */
if (*s && pg_mblen(s) == 1)
flag = *(unsigned char *) s; {
goto nextline; flag = *(unsigned char *) s;
} s++;
if (STRNCMP(recoded, "COMPOUNDFLAG") == 0 || STRNCMP(recoded, "COMPOUNDMIN") == 0 || if (*s == '\0' || *s == '#' || *s == '\n' || *s == ':' ||
STRNCMP(recoded, "PFX") == 0 || STRNCMP(recoded, "SFX") == 0) t_isspace(s))
{ {
if (oldformat) oldformat = true;
ereport(ERROR, goto nextline;
(errcode(ERRCODE_CONFIG_FILE_ERROR), }
errmsg("wrong affix file format for flag"))); }
tsearch_readline_end(&trst); goto isnewformat;
NIImportOOAffixes(Conf, filename);
return;
} }
if (STRNCMP(recoded, "COMPOUNDFLAG") == 0 ||
STRNCMP(recoded, "COMPOUNDMIN") == 0 ||
STRNCMP(recoded, "PFX") == 0 ||
STRNCMP(recoded, "SFX") == 0)
goto isnewformat;
if ((!suffixes) && (!prefixes)) if ((!suffixes) && (!prefixes))
goto nextline; goto nextline;
...@@ -888,6 +892,16 @@ nextline: ...@@ -888,6 +892,16 @@ nextline:
pfree(pstr); pfree(pstr);
} }
tsearch_readline_end(&trst); tsearch_readline_end(&trst);
return;
isnewformat:
if (oldformat)
ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("affix file contains both old-style and new-style commands")));
tsearch_readline_end(&trst);
NIImportOOAffixes(Conf, filename);
} }
static int static int
...@@ -1501,6 +1515,10 @@ CheckCompoundAffixes(CMPDAffix **ptr, char *word, int len, bool CheckInPlace) ...@@ -1501,6 +1515,10 @@ CheckCompoundAffixes(CMPDAffix **ptr, char *word, int len, bool CheckInPlace)
{ {
bool issuffix; bool issuffix;
/* in case CompoundAffix is null: */
if (*ptr == NULL)
return -1;
if (CheckInPlace) if (CheckInPlace)
{ {
while ((*ptr)->affix) while ((*ptr)->affix)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment