OSDN Git Service

Fix core dump in QTNodeCompare when tsquery_cmp() is applied to two empty
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 3 Aug 2010 00:10:39 +0000 (00:10 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 3 Aug 2010 00:10:39 +0000 (00:10 +0000)
tsqueries.  CompareTSQ has to have a guard for the case rather than blindly
applying QTNodeCompare to random data past the end of the datums.  Also,
change QTNodeCompare to be a little less trusting: use an actual test rather
than just Assert'ing that the input is sane.  Problem encountered while
investigating another issue (I saw a core dump in autoanalyze on a table
containing multiple empty tsquery values).

Back-patch to all branches with tsquery support.

In HEAD, also fix some bizarre (though not outright wrong) coding in
tsq_mcontains().

src/backend/utils/adt/tsquery_op.c
src/backend/utils/adt/tsquery_util.c

index 2b453e0..0b81ff5 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_op.c,v 1.8 2010/01/02 16:57:55 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_op.c,v 1.9 2010/08/03 00:10:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -149,7 +149,7 @@ CompareTSQ(TSQuery a, TSQuery b)
        {
                return (VARSIZE(a) < VARSIZE(b)) ? -1 : 1;
        }
-       else
+       else if (a->size != 0)
        {
                QTNode     *an = QT2QTN(GETQUERY(a), GETOPERAND(a));
                QTNode     *bn = QT2QTN(GETQUERY(b), GETOPERAND(b));
@@ -247,20 +247,20 @@ tsq_mcontains(PG_FUNCTION_ARGS)
                PG_RETURN_BOOL(false);
        }
 
+       iq = GETQUERY(query);
        ie = GETQUERY(ex);
 
        for (i = 0; i < ex->size; i++)
        {
-               iq = GETQUERY(query);
                if (ie[i].type != QI_VAL)
                        continue;
                for (j = 0; j < query->size; j++)
-                       if (iq[j].type == QI_VAL && ie[i].qoperand.valcrc == iq[j].qoperand.valcrc)
-                       {
-                               j = query->size + 1;
+               {
+                       if (iq[j].type == QI_VAL &&
+                               ie[i].qoperand.valcrc == iq[j].qoperand.valcrc)
                                break;
-                       }
-               if (j == query->size)
+               }
+               if (j >= query->size)
                {
                        PG_FREE_IF_COPY(query, 0);
                        PG_FREE_IF_COPY(ex, 1);
index ce8a892..5e309fe 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_util.c,v 1.13 2010/01/02 16:57:55 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_util.c,v 1.14 2010/08/03 00:10:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -113,13 +113,11 @@ QTNodeCompare(QTNode *an, QTNode *bn)
                }
                return 0;
        }
-       else
+       else if (an->valnode->type == QI_VAL)
        {
                QueryOperand *ao = &an->valnode->qoperand;
                QueryOperand *bo = &bn->valnode->qoperand;
 
-               Assert(an->valnode->type == QI_VAL);
-
                if (ao->valcrc != bo->valcrc)
                {
                        return (ao->valcrc > bo->valcrc) ? -1 : 1;
@@ -127,6 +125,11 @@ QTNodeCompare(QTNode *an, QTNode *bn)
 
                return tsCompareString(an->word, ao->length, bn->word, bo->length, false);
        }
+       else
+       {
+               elog(ERROR, "unrecognized QueryItem type: %d", an->valnode->type);
+               return 0;                               /* keep compiler quiet */
+       }
 }
 
 static int