Fix crash of to_tsvector() function on huge input: compareWORD()

function didn't return correct result for word position greate than
limit.

Per report from Stuart Bishop <stuart@stuartbishop.net>
This commit is contained in:
Teodor Sigaev 2007-09-26 10:09:57 +00:00
parent 10e1b9df5c
commit 689df1bc77

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tsearch/to_tsany.c,v 1.3 2007/09/10 12:36:40 teodor Exp $ * $PostgreSQL: pgsql/src/backend/tsearch/to_tsany.c,v 1.4 2007/09/26 10:09:57 teodor Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -40,7 +40,12 @@ compareWORD(const void *a, const void *b)
((ParsedWord *) b)->len); ((ParsedWord *) b)->len);
if (res == 0) if (res == 0)
{
if ( ((ParsedWord *) a)->pos.pos == ((ParsedWord *) b)->pos.pos )
return 0;
return (((ParsedWord *) a)->pos.pos > ((ParsedWord *) b)->pos.pos) ? 1 : -1; return (((ParsedWord *) a)->pos.pos > ((ParsedWord *) b)->pos.pos) ? 1 : -1;
}
return res; return res;
} }
return (((ParsedWord *) a)->len > ((ParsedWord *) b)->len) ? 1 : -1; return (((ParsedWord *) a)->len > ((ParsedWord *) b)->len) ? 1 : -1;
@ -66,18 +71,31 @@ uniqueWORD(ParsedWord * a, int4 l)
res = a; res = a;
ptr = a + 1; ptr = a + 1;
/*
* Sort words with its positions
*/
qsort((void *) a, l, sizeof(ParsedWord), compareWORD); qsort((void *) a, l, sizeof(ParsedWord), compareWORD);
/*
* Initialize first word and its first position
*/
tmppos = LIMITPOS(a->pos.pos); tmppos = LIMITPOS(a->pos.pos);
a->alen = 2; a->alen = 2;
a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen); a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen);
a->pos.apos[0] = 1; a->pos.apos[0] = 1;
a->pos.apos[1] = tmppos; a->pos.apos[1] = tmppos;
/*
* Summarize position information for each word
*/
while (ptr - a < l) while (ptr - a < l)
{ {
if (!(ptr->len == res->len && if (!(ptr->len == res->len &&
strncmp(ptr->word, res->word, res->len) == 0)) strncmp(ptr->word, res->word, res->len) == 0))
{ {
/*
* Got a new word, so put it in result
*/
res++; res++;
res->len = ptr->len; res->len = ptr->len;
res->word = ptr->word; res->word = ptr->word;
@ -89,8 +107,14 @@ uniqueWORD(ParsedWord * a, int4 l)
} }
else else
{ {
/*
* The word already exists, so adjust position information.
* But before we should check size of position's array,
* max allowed value for position and uniqueness of position
*/
pfree(ptr->word); pfree(ptr->word);
if (res->pos.apos[0] < MAXNUMPOS - 1 && res->pos.apos[res->pos.apos[0]] != MAXENTRYPOS - 1) if (res->pos.apos[0] < MAXNUMPOS - 1 && res->pos.apos[res->pos.apos[0]] != MAXENTRYPOS - 1 &&
res->pos.apos[res->pos.apos[0]] != LIMITPOS(ptr->pos.pos))
{ {
if (res->pos.apos[0] + 1 >= res->alen) if (res->pos.apos[0] + 1 >= res->alen)
{ {