A customer reported a mysterious crash, with the backtrace showing it to come from several levels down deep in the infix() function, called by tsqueryout(). I was eventually able to reproduce this and hunt down the bug, using the same tsquery string as the customer.

The bug was actually in to_tsquery(), and resulted in a corrupt "operand" string being stored in a tsquery Datum. In a nutshell, in to_tsquery_byid(), we're using memcpy() to copy to a possibly overlapping region of data. The obvious fix is to use memmove() instead, attached.

This is pretty hairy code, it's hard to resist doing some more whacking around. For example the infix() function would be a lot simpler if it used a StringInfo instead of implementing a resizeable string of its own. But I'll leave that alone for now, given that the bug was in fact not in that function.

--
  Heikki Linnakangas
  EnterpriseDB   http://www.enterprisedb.com
diff --git a/src/backend/tsearch/to_tsany.c b/src/backend/tsearch/to_tsany.c
index 5284c9c..9c5b3a3 100644
--- a/src/backend/tsearch/to_tsany.c
+++ b/src/backend/tsearch/to_tsany.c
@@ -342,6 +342,7 @@ to_tsquery_byid(PG_FUNCTION_ARGS)
 	if (query->size == 0)
 		PG_RETURN_TSQUERY(query);
 
+	/* clean out any stopword placeholders from the tree */
 	res = clean_fakeval(GETQUERY(query), &len);
 	if (!res)
 	{
@@ -351,6 +352,10 @@ to_tsquery_byid(PG_FUNCTION_ARGS)
 	}
 	memcpy((void *) GETQUERY(query), (void *) res, len * sizeof(QueryItem));
 
+	/*
+	 * Removing the stopword placeholders might've resulted in fewer
+	 * QueryItems. If so, move the operands up accordingly.
+	 */
 	if (len != query->size)
 	{
 		char	   *oldoperand = GETOPERAND(query);
@@ -359,7 +364,7 @@ to_tsquery_byid(PG_FUNCTION_ARGS)
 		Assert(len < query->size);
 
 		query->size = len;
-		memcpy((void *) GETOPERAND(query), oldoperand, VARSIZE(query) - (oldoperand - (char *) query));
+		memmove((void *) GETOPERAND(query), oldoperand, VARSIZE(query) - (oldoperand - (char *) query));
 		SET_VARSIZE(query, COMPUTESIZE(len, lenoperand));
 	}
 
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to