mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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.
This commit is contained in:
		@@ -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:
 | 
				
			|||||||
 * 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)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			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)
 | 
				
			|||||||
			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;
 | 
									flag = *(unsigned char *) s;
 | 
				
			||||||
 | 
									s++;
 | 
				
			||||||
 | 
									if (*s == '\0' || *s == '#' || *s == '\n' || *s == ':' ||
 | 
				
			||||||
 | 
										t_isspace(s))
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										oldformat = true;
 | 
				
			||||||
					goto nextline;
 | 
										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;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								goto isnewformat;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							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:
 | 
				
			|||||||
		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)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	bool		issuffix;
 | 
						bool		issuffix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* in case CompoundAffix is null: */
 | 
				
			||||||
 | 
						if (*ptr == NULL)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (CheckInPlace)
 | 
						if (CheckInPlace)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		while ((*ptr)->affix)
 | 
							while ((*ptr)->affix)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user