Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b3e0509

Browse files
committed
Fix not-terribly-safe coding in NIImportOOAffixes() and NIImportAffixes().
There were two places in spell.c that supposed that they could search for a location in a string produced by lowerstr() and then transpose the offset into the original string. But this fails completely if lowerstr() transforms any characters into characters of different byte length, as can happen in Turkish UTF8 for instance. We'd added some comments about this coding in commit 51e78ab, but failed to realize that it was not merely confusing but wrong. Coverity complained about this code years ago, but in such an opaque fashion that nobody understood what it was on about. I'm not entirely sure that this issue *is* what it's on about, actually, but perhaps this patch will shut it up -- and in any case the problem is clear. Back-patch to all supported branches.
1 parent cb0ca0c commit b3e0509

File tree

1 file changed

+19
-13
lines changed

1 file changed

+19
-13
lines changed

src/backend/tsearch/spell.c

+19-13
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,19 @@ findchar(char *str, int c)
219219
return NULL;
220220
}
221221

222+
static char *
223+
findchar2(char *str, int c1, int c2)
224+
{
225+
while (*str)
226+
{
227+
if (t_iseq(str, c1) || t_iseq(str, c2))
228+
return str;
229+
str += pg_mblen(str);
230+
}
231+
232+
return NULL;
233+
}
234+
222235

223236
/* backward string compare for suffix tree operations */
224237
static int
@@ -1262,18 +1275,13 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename)
12621275

12631276
if (flag == 0)
12641277
goto nextline;
1278+
/* Get flags after '/' (flags are case sensitive) */
1279+
if ((ptr = strchr(repl, '/')) != NULL)
1280+
aflg |= getFlagValues(Conf, getFlags(Conf, ptr + 1));
1281+
/* Get lowercased version of string before '/' */
12651282
prepl = lowerstr_ctx(Conf, repl);
1266-
/* Find position of '/' in lowercased string "prepl" */
12671283
if ((ptr = strchr(prepl, '/')) != NULL)
1268-
{
1269-
/*
1270-
* Here we use non-lowercased string "repl". We need position
1271-
* of '/' in "repl".
1272-
*/
12731284
*ptr = '\0';
1274-
ptr = repl + (ptr - prepl) + 1;
1275-
aflg |= getFlagValues(Conf, getFlags(Conf, ptr));
1276-
}
12771285
pfind = lowerstr_ctx(Conf, find);
12781286
pmask = lowerstr_ctx(Conf, mask);
12791287
if (t_iseq(find, '0'))
@@ -1343,12 +1351,10 @@ NIImportAffixes(IspellDict *Conf, const char *filename)
13431351

13441352
if (STRNCMP(pstr, "compoundwords") == 0)
13451353
{
1346-
/* Find position in lowercased string "pstr" */
1347-
s = findchar(pstr, 'l');
1354+
/* Find case-insensitive L flag in non-lowercased string */
1355+
s = findchar2(recoded, 'l', 'L');
13481356
if (s)
13491357
{
1350-
/* Here we use non-lowercased string "recoded" */
1351-
s = recoded + (s - pstr);
13521358
while (*s && !t_isspace(s))
13531359
s += pg_mblen(s);
13541360
while (*s && t_isspace(s))

0 commit comments

Comments
 (0)