postgres.git / summary / log / commit / refs
commit 19d290155d084754eeb5ebb2569654da06073ee8
Author: Teodor Sigaev <teodor@sigaev.ru>
Date: Fri Jul 15 16:22:18 2016 +0000
Fix nested NOT operation cleanup in tsquery.
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 | 8 +++++++-
src/test/regress/expected/tsearch.out | 12 ++++++++++++
src/test/regress/sql/tsearch.sql | 3 +++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/src/backend/utils/adt/tsquery_cleanup.c b/src/backend/utils/adt/tsquery_cleanup.c
index 1a90964ce79..8c2df73ea6b 100644
--- a/src/backend/utils/adt/tsquery_cleanup.c
+++ b/src/backend/utils/adt/tsquery_cleanup.c
@@ -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)
{
diff --git a/src/test/regress/expected/tsearch.out b/src/test/regress/expected/tsearch.out
index 2ec3d1b6ab9..129d06ef07e 100644
--- a/src/test/regress/expected/tsearch.out
+++ b/src/test/regress/expected/tsearch.out
@@ -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
-------------
diff --git a/src/test/regress/sql/tsearch.sql b/src/test/regress/sql/tsearch.sql
index 5f3d335fc39..65eb9438d49 100644
--- a/src/test/regress/sql/tsearch.sql
+++ b/src/test/regress/sql/tsearch.sql
@@ -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');
[parent: ce150e7e0fc1]