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)
Conf->usecompound = true;
}
/*
* Import an affix file that follows MySpell or Hunspell format
*/
static void
NIImportOOAffixes(IspellDict *Conf, const char *filename)
{
......@@ -757,6 +760,10 @@ nextline:
* import affixes
*
* 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
NIImportAffixes(IspellDict *Conf, const char *filename)
......@@ -833,13 +840,6 @@ NIImportAffixes(IspellDict *Conf, const char *filename)
while (*s && t_isspace(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 == '*')
{
......@@ -855,26 +855,30 @@ NIImportAffixes(IspellDict *Conf, const char *filename)
if (*s == '\\')
s++;
/* allow only single-encoded flags */
if (pg_mblen(s) != 1)
ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("multibyte flag character is not allowed")));
flag = *(unsigned char *) s;
goto nextline;
}
if (STRNCMP(recoded, "COMPOUNDFLAG") == 0 || STRNCMP(recoded, "COMPOUNDMIN") == 0 ||
STRNCMP(recoded, "PFX") == 0 || STRNCMP(recoded, "SFX") == 0)
{
if (oldformat)
ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("wrong affix file format for flag")));
tsearch_readline_end(&trst);
NIImportOOAffixes(Conf, filename);
return;
/*
* An old-format flag is a single ASCII character; we expect it to
* be followed by EOL, whitespace, or ':'. Otherwise this is a
* new-format flag command.
*/
if (*s && pg_mblen(s) == 1)
{
flag = *(unsigned char *) s;
s++;
if (*s == '\0' || *s == '#' || *s == '\n' || *s == ':' ||
t_isspace(s))
{
oldformat = true;
goto nextline;
}
}
goto isnewformat;
}
if (STRNCMP(recoded, "COMPOUNDFLAG") == 0 ||
STRNCMP(recoded, "COMPOUNDMIN") == 0 ||
STRNCMP(recoded, "PFX") == 0 ||
STRNCMP(recoded, "SFX") == 0)
goto isnewformat;
if ((!suffixes) && (!prefixes))
goto nextline;
......@@ -888,6 +892,16 @@ nextline:
pfree(pstr);
}
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
......@@ -1501,6 +1515,10 @@ CheckCompoundAffixes(CMPDAffix **ptr, char *word, int len, bool CheckInPlace)
{
bool issuffix;
/* in case CompoundAffix is null: */
if (*ptr == NULL)
return -1;
if (CheckInPlace)
{
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