]> granicus.if.org Git - postgresql/commitdiff
Fix nested NOT operation cleanup in tsquery.
authorTeodor Sigaev <teodor@sigaev.ru>
Fri, 15 Jul 2016 16:22:18 +0000 (19:22 +0300)
committerTeodor Sigaev <teodor@sigaev.ru>
Fri, 15 Jul 2016 16:22:18 +0000 (19:22 +0300)
During normalization of tsquery tree it tries to simplify nested NOT
operations but there it's obvioulsy missed that subsequent node could be
a leaf node (value node)

Bug #14245: Segfault on weird to_tsquery
Reported by David Kellum.

src/backend/utils/adt/tsquery_cleanup.c
src/test/regress/expected/tsearch.out
src/test/regress/sql/tsearch.sql

index 1a90964ce79d470f6d645c1ecd32d5150964b6af..8c2df73ea6b72351ba06055b97e3325b7566a581 100644 (file)
@@ -406,6 +406,8 @@ normalize_phrase_tree(NODE *node)
 
        if (node->valnode->qoperator.oper == OP_NOT)
        {
+               NODE *orignode = node;
+
                /* eliminate NOT sequence */
                while (node->valnode->type == QI_OPR &&
                node->valnode->qoperator.oper == node->right->valnode->qoperator.oper)
@@ -413,7 +415,11 @@ normalize_phrase_tree(NODE *node)
                        node = node->right->right;
                }
 
-               node->right = normalize_phrase_tree(node->right);
+               if (orignode != node)
+                       /* current node isn't checked yet */
+                       node = normalize_phrase_tree(node);
+               else
+                       node->right = normalize_phrase_tree(node->right);
        }
        else if (node->valnode->qoperator.oper == OP_PHRASE)
        {
index 2ec3d1b6ab94e6cad1aef5b65b2f98eb39156376..129d06ef07ea430a0e05603ffc7849fcb5a79a4a 100644 (file)
@@ -555,6 +555,18 @@ SELECT plainto_tsquery('english', 'foo bar') && 'asd | fg';
 (1 row)
 
 -- Check stop word deletion, a and s are stop-words
+SELECT to_tsquery('english', '!(a & !b) & c');
+ to_tsquery 
+------------
+ 'b' & 'c'
+(1 row)
+
+SELECT to_tsquery('english', '!(a & !b)');
+ to_tsquery 
+------------
+ 'b'
+(1 row)
+
 SELECT to_tsquery('english', '(1 <-> 2) <-> a');
  to_tsquery  
 -------------
index 5f3d335fc393c724e297d79f576193315b5df8a7..65eb9438d4941212552c94ec05356ebd0c3ead5f 100644 (file)
@@ -130,6 +130,9 @@ SELECT plainto_tsquery('english', 'foo bar') || !!plainto_tsquery('english', 'as
 SELECT plainto_tsquery('english', 'foo bar') && 'asd | fg';
 
 -- Check stop word deletion, a and s are stop-words
+SELECT to_tsquery('english', '!(a & !b) & c');
+SELECT to_tsquery('english', '!(a & !b)');
+
 SELECT to_tsquery('english', '(1 <-> 2) <-> a');
 SELECT to_tsquery('english', '(1 <-> a) <-> 2');
 SELECT to_tsquery('english', '(a <-> 1) <-> 2');