mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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
This commit is contained in:
		@@ -458,6 +458,8 @@ IsAffixFlagInUse(IspellDict *Conf, int affix, char *affixflag)
 | 
				
			|||||||
	if (*affixflag == 0)
 | 
						if (*affixflag == 0)
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Assert(affix < Conf->nAffixData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flagcur = Conf->AffixData[affix];
 | 
						flagcur = Conf->AffixData[affix];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (*flagcur)
 | 
						while (*flagcur)
 | 
				
			||||||
@@ -1160,13 +1162,17 @@ getAffixFlagSet(IspellDict *Conf, char *s)
 | 
				
			|||||||
					(errcode(ERRCODE_CONFIG_FILE_ERROR),
 | 
										(errcode(ERRCODE_CONFIG_FILE_ERROR),
 | 
				
			||||||
					 errmsg("invalid affix alias \"%s\"", s)));
 | 
										 errmsg("invalid affix alias \"%s\"", s)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (curaffix > 0 && curaffix <= Conf->nAffixData)
 | 
							if (curaffix > 0 && curaffix < Conf->nAffixData)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * Do not subtract 1 from curaffix because empty string was added
 | 
								 * Do not subtract 1 from curaffix because empty string was added
 | 
				
			||||||
			 * in NIImportOOAffixes
 | 
								 * in NIImportOOAffixes
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			return Conf->AffixData[curaffix];
 | 
								return Conf->AffixData[curaffix];
 | 
				
			||||||
 | 
							else if (curaffix > Conf->nAffixData)
 | 
				
			||||||
 | 
								ereport(ERROR,
 | 
				
			||||||
 | 
										(errcode(ERRCODE_CONFIG_FILE_ERROR),
 | 
				
			||||||
 | 
										 errmsg("invalid affix alias \"%s\"", s)));
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			return VoidString;
 | 
								return VoidString;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1556,6 +1562,8 @@ MergeAffix(IspellDict *Conf, int a1, int a2)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	char	  **ptr;
 | 
						char	  **ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Assert(a1 < Conf->nAffixData && a2 < Conf->nAffixData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Do not merge affix flags if one of affix flags is empty */
 | 
						/* Do not merge affix flags if one of affix flags is empty */
 | 
				
			||||||
	if (*Conf->AffixData[a1] == '\0')
 | 
						if (*Conf->AffixData[a1] == '\0')
 | 
				
			||||||
		return a2;
 | 
							return a2;
 | 
				
			||||||
@@ -1598,9 +1606,10 @@ MergeAffix(IspellDict *Conf, int a1, int a2)
 | 
				
			|||||||
static uint32
 | 
					static uint32
 | 
				
			||||||
makeCompoundFlags(IspellDict *Conf, int affix)
 | 
					makeCompoundFlags(IspellDict *Conf, int affix)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char	   *str = Conf->AffixData[affix];
 | 
						Assert(affix < Conf->nAffixData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (getCompoundAffixFlagValue(Conf, str) & FF_COMPOUNDFLAGMASK);
 | 
						return (getCompoundAffixFlagValue(Conf, Conf->AffixData[affix]) &
 | 
				
			||||||
 | 
								FF_COMPOUNDFLAGMASK);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -1720,6 +1729,16 @@ NISortDictionary(IspellDict *Conf)
 | 
				
			|||||||
							(errcode(ERRCODE_CONFIG_FILE_ERROR),
 | 
												(errcode(ERRCODE_CONFIG_FILE_ERROR),
 | 
				
			||||||
							 errmsg("invalid affix alias \"%s\"",
 | 
												 errmsg("invalid affix alias \"%s\"",
 | 
				
			||||||
									Conf->Spell[i]->p.flag)));
 | 
														Conf->Spell[i]->p.flag)));
 | 
				
			||||||
 | 
									if (curaffix < 0 || curaffix >= Conf->nAffixData)
 | 
				
			||||||
 | 
										ereport(ERROR,
 | 
				
			||||||
 | 
												(errcode(ERRCODE_CONFIG_FILE_ERROR),
 | 
				
			||||||
 | 
												 errmsg("invalid affix alias \"%s\"",
 | 
				
			||||||
 | 
														Conf->Spell[i]->p.flag)));
 | 
				
			||||||
 | 
									if (*end != '\0' && !t_isdigit(end) && !t_isspace(end))
 | 
				
			||||||
 | 
										ereport(ERROR,
 | 
				
			||||||
 | 
												(errcode(ERRCODE_CONFIG_FILE_ERROR),
 | 
				
			||||||
 | 
												 errmsg("invalid affix alias \"%s\"",
 | 
				
			||||||
 | 
														Conf->Spell[i]->p.flag)));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -383,6 +383,40 @@ SELECT ts_lexize('hunspell_num', 'footballyklubber');
 | 
				
			|||||||
 {foot,ball,klubber}
 | 
					 {foot,ball,klubber}
 | 
				
			||||||
(1 row)
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- Test suitability of affix and dict files
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_err (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=ispell_sample,
 | 
				
			||||||
 | 
											AffFile=hunspell_sample_long
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					ERROR:  invalid affix alias "GJUS"
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_err (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=ispell_sample,
 | 
				
			||||||
 | 
											AffFile=hunspell_sample_num
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					ERROR:  invalid affix flag "SZ\"
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_invalid_1 (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=hunspell_sample_long,
 | 
				
			||||||
 | 
											AffFile=ispell_sample
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_invalid_2 (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=hunspell_sample_long,
 | 
				
			||||||
 | 
											AffFile=hunspell_sample_num
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_invalid_3 (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=hunspell_sample_num,
 | 
				
			||||||
 | 
											AffFile=ispell_sample
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_err (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=hunspell_sample_num,
 | 
				
			||||||
 | 
											AffFile=hunspell_sample_long
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					ERROR:  invalid affix alias "302,301,202,303"
 | 
				
			||||||
-- Synonym dictionary
 | 
					-- Synonym dictionary
 | 
				
			||||||
CREATE TEXT SEARCH DICTIONARY synonym (
 | 
					CREATE TEXT SEARCH DICTIONARY synonym (
 | 
				
			||||||
						Template=synonym,
 | 
											Template=synonym,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -96,6 +96,43 @@ SELECT ts_lexize('hunspell_num', 'footballklubber');
 | 
				
			|||||||
SELECT ts_lexize('hunspell_num', 'ballyklubber');
 | 
					SELECT ts_lexize('hunspell_num', 'ballyklubber');
 | 
				
			||||||
SELECT ts_lexize('hunspell_num', 'footballyklubber');
 | 
					SELECT ts_lexize('hunspell_num', 'footballyklubber');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- Test suitability of affix and dict files
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_err (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=ispell_sample,
 | 
				
			||||||
 | 
											AffFile=hunspell_sample_long
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_err (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=ispell_sample,
 | 
				
			||||||
 | 
											AffFile=hunspell_sample_num
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_invalid_1 (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=hunspell_sample_long,
 | 
				
			||||||
 | 
											AffFile=ispell_sample
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_invalid_2 (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=hunspell_sample_long,
 | 
				
			||||||
 | 
											AffFile=hunspell_sample_num
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_invalid_3 (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=hunspell_sample_num,
 | 
				
			||||||
 | 
											AffFile=ispell_sample
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TEXT SEARCH DICTIONARY hunspell_err (
 | 
				
			||||||
 | 
											Template=ispell,
 | 
				
			||||||
 | 
											DictFile=hunspell_sample_num,
 | 
				
			||||||
 | 
											AffFile=hunspell_sample_long
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- Synonym dictionary
 | 
					-- Synonym dictionary
 | 
				
			||||||
CREATE TEXT SEARCH DICTIONARY synonym (
 | 
					CREATE TEXT SEARCH DICTIONARY synonym (
 | 
				
			||||||
						Template=synonym,
 | 
											Template=synonym,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user