Skip to content

Commit b15e8f7

Browse files
committed
Fix broken collation-aware searches in SP-GiST text opclass.
spg_text_leaf_consistent() supposed that it should compare only Min(querylen, entrylen) bytes of the two strings, and then deal with any excess bytes in one string or the other by assuming the longer string is greater if the prefixes are equal. Quite aside from the fact that that's just wrong in some locales (e.g., 'ch' is not less than 'd' in cs_CZ), it also risked passing incomplete multibyte characters to strcoll(), with ensuing bad results. Instead, just pass the full strings to varstr_cmp, and let it decide what to do about unequal-length strings. Fortunately, this error doesn't imply any index corruption, it's just that searches might return the wrong set of entries. Per report from Emre Hasegeli, though this is not his patch. Thanks to Peter Geoghegan for review and discussion. This code was born broken, so back-patch to all supported branches. In HEAD, I failed to resist the temptation to do a bit of cosmetic cleanup/pgindent'ing on 710d90d, too. Discussion: https://postgr.es/m/CAE2gYzzb6K51VnTq5i5p52z+j9p2duEa-K1T3RrC_GQEynAKEg@mail.gmail.com
1 parent 22ff2b8 commit b15e8f7

File tree

1 file changed

+15
-15
lines changed

1 file changed

+15
-15
lines changed

src/backend/access/spgist/spgtextproc.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -626,15 +626,15 @@ spg_text_leaf_consistent(PG_FUNCTION_ARGS)
626626
if (strategy == RTPrefixStrategyNumber)
627627
{
628628
/*
629-
* if level >= length of query then reconstrValue is began with
630-
* query (prefix) string and we don't need to check it again.
629+
* if level >= length of query then reconstrValue must begin with
630+
* query (prefix) string, so we don't need to check it again.
631631
*/
632-
633632
res = (level >= queryLen) ||
634-
DatumGetBool(DirectFunctionCall2(text_starts_with,
635-
out->leafValue, PointerGetDatum(query)));
633+
DatumGetBool(DirectFunctionCall2(text_starts_with,
634+
out->leafValue,
635+
PointerGetDatum(query)));
636636

637-
if (!res) /* no need to consider remaining conditions */
637+
if (!res) /* no need to consider remaining conditions */
638638
break;
639639

640640
continue;
@@ -648,22 +648,22 @@ spg_text_leaf_consistent(PG_FUNCTION_ARGS)
648648
/* If asserts enabled, verify encoding of reconstructed string */
649649
Assert(pg_verifymbstr(fullValue, fullLen, false));
650650

651-
r = varstr_cmp(fullValue, Min(queryLen, fullLen),
652-
VARDATA_ANY(query), Min(queryLen, fullLen),
651+
r = varstr_cmp(fullValue, fullLen,
652+
VARDATA_ANY(query), queryLen,
653653
PG_GET_COLLATION());
654654
}
655655
else
656656
{
657657
/* Non-collation-aware comparison */
658658
r = memcmp(fullValue, VARDATA_ANY(query), Min(queryLen, fullLen));
659-
}
660659

661-
if (r == 0)
662-
{
663-
if (queryLen > fullLen)
664-
r = -1;
665-
else if (queryLen < fullLen)
666-
r = 1;
660+
if (r == 0)
661+
{
662+
if (queryLen > fullLen)
663+
r = -1;
664+
else if (queryLen < fullLen)
665+
r = 1;
666+
}
667667
}
668668

669669
switch (strategy)

0 commit comments

Comments
 (0)