aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-10-23 13:11:28 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2014-10-23 13:12:00 -0400
commitb34d6f03dbb34027ee0ee6f1c1887ae30ec7b07d (patch)
treecd0674724debeb40b876c6c8265badb2566c70ef /src
parent2781b4bea7db357be59f9a5fd73ca1eb12ff5a79 (diff)
downloadpostgresql-b34d6f03dbb34027ee0ee6f1c1887ae30ec7b07d.tar.gz
postgresql-b34d6f03dbb34027ee0ee6f1c1887ae30ec7b07d.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/tsearch/spell.c70
1 files changed, 44 insertions, 26 deletions
diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c
index 530c6eddb8c..b32dc471aa3 100644
--- a/src/backend/tsearch/spell.c
+++ b/src/backend/tsearch/spell.c
@@ -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)