Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions bigm.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,13 @@ typedef struct
#define GETARR(x) ( (bigm *)( (char*)x + VARHDRSZ ) )
#define ARRNELEM(x) ( ( VARSIZE(x) - VARHDRSZ )/sizeof(bigm) )

#if PG_VERSION_NUM >= 180000
extern int t_isspace(const char *ptr);
#if PG_VERSION_NUM < 140000
extern int t_isspace_with_len(const char *ptr, int mblen);
extern int pg_mblen_with_len(const char *mbstr, int limit);
extern int pg_mblen_range(const char *mbstr, const char *end);
extern int pg_mblen_unbounded(const char *mbstr);
#elif PG_VERSION_NUM >= 180000
extern int t_isspace_with_len(const char *ptr, int mblen);
#endif

extern BIGM *generate_bigm(char *str, int slen);
Expand Down
9 changes: 5 additions & 4 deletions bigm_gin.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,17 +150,18 @@ gin_extract_query_bigm(PG_FUNCTION_ARGS)
if (bgmlen == 1 && !removeDups)
{
const char *sp;
const char *endstr = str + slen;

*recheck = false;
for (sp = str; (sp - str) < slen;)
{
if (t_isspace(sp))
if (t_isspace_with_len(sp, slen))
{
*recheck = true;
break;
}

sp += IS_HIGHBIT_SET(*sp) ? pg_mblen(sp) : 1;
sp += IS_HIGHBIT_SET(*sp) ? pg_mblen_range(sp, endstr) : 1;
}
}
else
Expand Down Expand Up @@ -374,8 +375,8 @@ gin_bigm_compare_partial(PG_FUNCTION_ARGS)
a1p = VARDATA_ANY(arg1);
a2p = VARDATA_ANY(arg2);

mblen1 = pg_mblen(a1p);
mblen2 = pg_mblen(a2p);
mblen1 = pg_mblen_with_len(a1p, VARSIZE_ANY_EXHDR(arg1));
mblen2 = pg_mblen_with_len(a2p, VARSIZE_ANY_EXHDR(arg2));

if (mblen1 != mblen2)
PG_RETURN_INT32(1);
Expand Down
85 changes: 62 additions & 23 deletions bigm_op.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,53 @@ unique_array(bigm *a, int len)
return curend + 1 - a;
}

#if PG_VERSION_NUM >= 180000
#if PG_VERSION_NUM < 140000
/*
* t_isspace() and pg_mblen() were replaced with bound-checked versions
* in commit 1e7fe06c10 and were backported to PostgreSQL 14.
*
* Supporting the full logic of these new APIs in PostgreSQL 13 and earlier
* would require significant backporting effort. For compatibility, we
* provide these shims that map to the original t_isspace() and pg_mblen()
* implementations for legacy releases.
*/
int
t_isspace_with_len(const char *ptr, int mblen)
{
return t_isspace(ptr);
}

int
pg_mblen_with_len(const char *mbstr, int limit)
{
return pg_mblen(mbstr);
}

int
pg_mblen_range(const char *mbstr, const char *end)
{
return pg_mblen(mbstr);
}

int
pg_mblen_unbounded(const char *mbstr)
{
return pg_mblen(mbstr);
}

#elif PG_VERSION_NUM >= 180000
/*
* This function is equivalent to isspace() but supports multibyte
* characters and encoding. It was part of PostgreSQL 17 and earlier
* but was removed in commit d3aad4ac57c. This version is copied
* from PostgreSQL 17.
* characters and encoding. It was part of PostgreSQL core through
* version 17 but was removed in commit d3aad4ac57c and was replaced
* with t_isspace_with_len() to prevent buffer overruns. This version
* is copied from PostgreSQL 17.
*/
int
t_isspace(const char *ptr)
t_isspace_with_len(const char *ptr, int mblen)
{
#define WC_BUF_LEN 3
int clen = pg_mblen(ptr);
int clen = pg_mblen_with_len(ptr, mblen);
wchar_t character[WC_BUF_LEN];
#if PG_VERSION_NUM >= 190000
locale_t mylocale = 0; /* TODO */
Expand All @@ -181,9 +216,9 @@ t_isspace(const char *ptr)

return iswspace((wint_t) character[0]);
}
#endif /* PG_VERSION_NUM >= 180000 */
#endif

#define iswordchr(c) (!t_isspace(c))
#define iswordchr(c, len) (!t_isspace_with_len(c, len))

/*
* Finds first word in string, returns pointer to the word,
Expand All @@ -193,18 +228,19 @@ static char *
find_word(char *str, int lenstr, char **endword, int *charlen)
{
char *beginword = str;
const char *endstr = str + lenstr;

while (beginword - str < lenstr && !iswordchr(beginword))
beginword += pg_mblen(beginword);
while (beginword - str < lenstr && !iswordchr(beginword, lenstr))
beginword += pg_mblen_range(beginword, endstr);

if (beginword - str >= lenstr)
return NULL;

*endword = beginword;
*charlen = 0;
while (*endword - str < lenstr && iswordchr(*endword))
while (*endword - str < lenstr && iswordchr(*endword, lenstr))
{
*endword += pg_mblen(*endword);
*endword += pg_mblen_range(*endword, endstr);
(*charlen)++;
}

Expand Down Expand Up @@ -232,7 +268,7 @@ make_bigrams(bigm *bptr, char *str, int bytelen, int charlen)

if (charlen < 2)
{
compact_bigram(bptr, ptr, pg_mblen(str));
compact_bigram(bptr, ptr, pg_mblen_unbounded(str));
bptr->pmatch = true;
bptr++;
return bptr;
Expand All @@ -241,8 +277,8 @@ make_bigrams(bigm *bptr, char *str, int bytelen, int charlen)
if (bytelen > charlen)
{
/* Find multibyte character boundaries and call compact_bigram */
int lenfirst = pg_mblen(str),
lenlast = pg_mblen(str + lenfirst);
int lenfirst = pg_mblen_unbounded(str),
lenlast = pg_mblen_unbounded(str + lenfirst);

while ((ptr - str) + lenfirst + lenlast <= bytelen)
{
Expand All @@ -254,7 +290,7 @@ make_bigrams(bigm *bptr, char *str, int bytelen, int charlen)
lenfirst = lenlast;
if ((ptr - str) + lenfirst >= bytelen)
break;
lenlast = pg_mblen(ptr + lenfirst);
lenlast = pg_mblen_unbounded(ptr + lenfirst);
}
}
else
Expand Down Expand Up @@ -371,6 +407,7 @@ get_wildcard_part(const char *str, int lenstr,
{
const char *beginword = str;
const char *endword;
const char *endstr = str + lenstr;
char *s = buf;
bool in_leading_wildcard_meta = false;
bool in_trailing_wildcard_meta = false;
Expand All @@ -387,7 +424,7 @@ get_wildcard_part(const char *str, int lenstr,
{
if (in_escape)
{
if (iswordchr(beginword))
if (iswordchr(beginword, lenstr))
break;
in_escape = false;
in_leading_wildcard_meta = false;
Expand All @@ -398,12 +435,12 @@ get_wildcard_part(const char *str, int lenstr,
in_escape = true;
else if (ISWILDCARDCHAR(beginword))
in_leading_wildcard_meta = true;
else if (iswordchr(beginword))
else if (iswordchr(beginword, lenstr))
break;
else
in_leading_wildcard_meta = false;
}
beginword += pg_mblen(beginword);
beginword += pg_mblen_range(beginword, endstr);
}

/*
Expand Down Expand Up @@ -438,10 +475,10 @@ get_wildcard_part(const char *str, int lenstr,
endword = beginword;
while (endword - str < lenstr)
{
clen = pg_mblen(endword);
clen = pg_mblen_range(endword, endstr);
if (in_escape)
{
if (iswordchr(endword))
if (iswordchr(endword, lenstr))
{
memcpy(s, endword, clen);
(*charlen)++;
Expand Down Expand Up @@ -469,7 +506,7 @@ get_wildcard_part(const char *str, int lenstr,
in_trailing_wildcard_meta = true;
break;
}
else if (iswordchr(endword))
else if (iswordchr(endword, lenstr))
{
memcpy(s, endword, clen);
(*charlen)++;
Expand Down Expand Up @@ -701,6 +738,7 @@ likequery(PG_FUNCTION_ARGS)
{
text *query = PG_GETARG_TEXT_PP(0);
const char *str;
const char *endstr;
int len;
const char *sp;
text *result;
Expand All @@ -709,6 +747,7 @@ likequery(PG_FUNCTION_ARGS)

str = VARDATA_ANY(query);
len = VARSIZE_ANY_EXHDR(query);
endstr = str + len;

if (len == 0)
PG_RETURN_NULL();
Expand All @@ -726,7 +765,7 @@ likequery(PG_FUNCTION_ARGS)
}
else if (IS_HIGHBIT_SET(*sp))
{
mblen = pg_mblen(sp);
mblen = pg_mblen_range(sp, endstr);
memcpy(rp, sp, mblen);
rp += mblen;
sp += mblen;
Expand Down