Skip to content

Commit 19d2901

Browse files
committed
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.
1 parent ce150e7 commit 19d2901

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

src/backend/utils/adt/tsquery_cleanup.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -406,14 +406,20 @@ normalize_phrase_tree(NODE *node)
406406

407407
if (node->valnode->qoperator.oper == OP_NOT)
408408
{
409+
NODE *orignode = node;
410+
409411
/* eliminate NOT sequence */
410412
while (node->valnode->type == QI_OPR &&
411413
node->valnode->qoperator.oper == node->right->valnode->qoperator.oper)
412414
{
413415
node = node->right->right;
414416
}
415417

416-
node->right = normalize_phrase_tree(node->right);
418+
if (orignode != node)
419+
/* current node isn't checked yet */
420+
node = normalize_phrase_tree(node);
421+
else
422+
node->right = normalize_phrase_tree(node->right);
417423
}
418424
else if (node->valnode->qoperator.oper == OP_PHRASE)
419425
{

src/test/regress/expected/tsearch.out

+12
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,18 @@ SELECT plainto_tsquery('english', 'foo bar') && 'asd | fg';
555555
(1 row)
556556

557557
-- Check stop word deletion, a and s are stop-words
558+
SELECT to_tsquery('english', '!(a & !b) & c');
559+
to_tsquery
560+
------------
561+
'b' & 'c'
562+
(1 row)
563+
564+
SELECT to_tsquery('english', '!(a & !b)');
565+
to_tsquery
566+
------------
567+
'b'
568+
(1 row)
569+
558570
SELECT to_tsquery('english', '(1 <-> 2) <-> a');
559571
to_tsquery
560572
-------------

src/test/regress/sql/tsearch.sql

+3
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ SELECT plainto_tsquery('english', 'foo bar') || !!plainto_tsquery('english', 'as
130130
SELECT plainto_tsquery('english', 'foo bar') && 'asd | fg';
131131

132132
-- Check stop word deletion, a and s are stop-words
133+
SELECT to_tsquery('english', '!(a & !b) & c');
134+
SELECT to_tsquery('english', '!(a & !b)');
135+
133136
SELECT to_tsquery('english', '(1 <-> 2) <-> a');
134137
SELECT to_tsquery('english', '(1 <-> a) <-> 2');
135138
SELECT to_tsquery('english', '(a <-> 1) <-> 2');

0 commit comments

Comments
 (0)