Skip to content

Commit

Permalink
Fix issue 1303: Server crashes on executing SELECT * FROM agtype(null…
Browse files Browse the repository at this point in the history
…); (#1317)

* Add additional checks for Const expression nodes for which the
      walker code would crash.

    * The server crashes for few other expr types too including Const,
      OpExpr, Var, BoolExpr and CoerceViaIO for which checks are added

    * Add regression tests
  • Loading branch information
Zainab-Saad authored and jrgemignani committed Dec 13, 2023
1 parent 2f98aca commit 105b78e
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 6 deletions.
156 changes: 156 additions & 0 deletions regress/expected/expr.out
Original file line number Diff line number Diff line change
Expand Up @@ -7304,6 +7304,152 @@ SELECT results, pg_typeof(user) FROM cypher('issue_1124', $$ MATCH (u) RETURN u
{"id": 281474976710657, "label": "", "properties": {}}::vertex | name
(1 row)

--
-- issue 1303: segmentation fault on queries like SELECT * FROM agtype(null);
--
-- Test Const and CoerceViaIO expression node types
SELECT * FROM agtype(null);
agtype
--------

(1 row)

SELECT * FROM agtype('1');
agtype
--------
1
(1 row)

SELECT * FROM agtype('[1, 2, 3]');
agtype
-----------
[1, 2, 3]
(1 row)

SELECT * FROM agtype('{"a": 1}');
agtype
----------
{"a": 1}
(1 row)

SELECT * FROM agtype('{"id": 844424930131971, "label": "v", "properties": {"i": 1}}::vertex');
agtype
-----------------------------------------------------------------------
{"id": 844424930131971, "label": "v", "properties": {"i": 1}}::vertex
(1 row)

SELECT * FROM agtype('{"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge');
agtype
---------------------------------------------------------------------------------------------------------------------------
{"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
(1 row)

SELECT * FROM agtype('[{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path');
agtype
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path
(1 row)

SELECT * FROM text(1);
text
------
1
(1 row)

SELECT * FROM text('1');
text
------
1
(1 row)

SELECT * FROM int4(1);
int4
------
1
(1 row)

SELECT * FROM json('1');
json
------
1
(1 row)

SELECT * FROM jsonb('1');
jsonb
-------
1
(1 row)

SELECT * FROM bytea('1');
bytea
-------
\x31
(1 row)

-- Test Var expression node types
SELECT create_graph('issue_1303');
NOTICE: graph "issue_1303" has been created
create_graph
--------------

(1 row)

SELECT result, agtype('[1, 2, 3]') FROM cypher('issue_1303', $$ CREATE (u) RETURN u $$) AS (result agtype);
result | agtype
----------------------------------------------------------------+-----------
{"id": 281474976710657, "label": "", "properties": {}}::vertex | [1, 2, 3]
(1 row)

SELECT result, result2, pg_typeof(result2) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), agtype('[1, 2, 3]') AS result2;
result | result2 | pg_typeof
----------------------------------------------------------------+-----------+-----------
{"id": 281474976710657, "label": "", "properties": {}}::vertex | [1, 2, 3] | agtype
(1 row)

SELECT result, result2, pg_typeof(result2) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2;
result | result2 | pg_typeof
----------------------------------------------------------------+---------+-----------
{"id": 281474976710657, "label": "", "properties": {}}::vertex | 1 | text
(1 row)

SELECT result, result2, pg_typeof(result2), result3, pg_typeof(result3) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2, agtype(result) AS result3;
result | result2 | pg_typeof | result3 | pg_typeof
----------------------------------------------------------------+---------+-----------+----------------------------------------------------------------+-----------
{"id": 281474976710657, "label": "", "properties": {}}::vertex | 1 | text | {"id": 281474976710657, "label": "", "properties": {}}::vertex | agtype
(1 row)

SELECT result, result2, pg_typeof(result2), result3, pg_typeof(result3) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2, agtype(result2) AS result3;
result | result2 | pg_typeof | result3 | pg_typeof
----------------------------------------------------------------+---------+-----------+---------+-----------
{"id": 281474976710657, "label": "", "properties": {}}::vertex | 1 | text | 1 | agtype
(1 row)

-- Text OpExpr expression node types
SELECT * FROM agtype('[1, 2, 3]'::agtype || '[5, 6, 7]');
agtype
--------------------
[1, 2, 3, 5, 6, 7]
(1 row)

SELECT * FROM agtype('[1, 2, 3]'::agtype -> 2);
agtype
--------
3
(1 row)

SELECT * FROM agtype('{"a": 1, "b": 2}'::agtype -> 'a'::text);
agtype
--------
1
(1 row)

-- Text BoolExpr expression node types
SELECT * FROM bool(true AND false);
bool
------
f
(1 row)

--
-- Cleanup
--
Expand All @@ -7317,6 +7463,16 @@ NOTICE: graph "issue_1124" has been dropped

(1 row)

SELECT * FROM drop_graph('issue_1303', true);
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table issue_1303._ag_label_vertex
drop cascades to table issue_1303._ag_label_edge
NOTICE: graph "issue_1303" has been dropped
drop_graph
------------

(1 row)

SELECT * FROM drop_graph('graph_395', true);
NOTICE: drop cascades to 7 other objects
DETAIL: drop cascades to table graph_395._ag_label_vertex
Expand Down
37 changes: 37 additions & 0 deletions regress/sql/expr.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2986,10 +2986,47 @@ SELECT * FROM create_graph('issue_1124');
SELECT results, pg_typeof(user) FROM cypher('issue_1124', $$ CREATE (u) RETURN u $$) AS (results agtype), user;
SELECT results, pg_typeof(user) FROM cypher('issue_1124', $$ MATCH (u) RETURN u $$) AS (results agtype), user;

--
-- issue 1303: segmentation fault on queries like SELECT * FROM agtype(null);
--

-- Test Const and CoerceViaIO expression node types
SELECT * FROM agtype(null);
SELECT * FROM agtype('1');
SELECT * FROM agtype('[1, 2, 3]');
SELECT * FROM agtype('{"a": 1}');
SELECT * FROM agtype('{"id": 844424930131971, "label": "v", "properties": {"i": 1}}::vertex');
SELECT * FROM agtype('{"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge');
SELECT * FROM agtype('[{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex, {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge, {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex, {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge, {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path');

SELECT * FROM text(1);
SELECT * FROM text('1');
SELECT * FROM int4(1);
SELECT * FROM json('1');
SELECT * FROM jsonb('1');
SELECT * FROM bytea('1');

-- Test Var expression node types
SELECT create_graph('issue_1303');
SELECT result, agtype('[1, 2, 3]') FROM cypher('issue_1303', $$ CREATE (u) RETURN u $$) AS (result agtype);
SELECT result, result2, pg_typeof(result2) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), agtype('[1, 2, 3]') AS result2;
SELECT result, result2, pg_typeof(result2) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2;
SELECT result, result2, pg_typeof(result2), result3, pg_typeof(result3) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2, agtype(result) AS result3;
SELECT result, result2, pg_typeof(result2), result3, pg_typeof(result3) FROM cypher('issue_1303', $$ MATCH (u) RETURN u $$) AS (result agtype), text(1) AS result2, agtype(result2) AS result3;

-- Text OpExpr expression node types
SELECT * FROM agtype('[1, 2, 3]'::agtype || '[5, 6, 7]');
SELECT * FROM agtype('[1, 2, 3]'::agtype -> 2);
SELECT * FROM agtype('{"a": 1, "b": 2}'::agtype -> 'a'::text);

-- Text BoolExpr expression node types
SELECT * FROM bool(true AND false);

--
-- Cleanup
--
SELECT * FROM drop_graph('issue_1124', true);
SELECT * FROM drop_graph('issue_1303', true);
SELECT * FROM drop_graph('graph_395', true);
SELECT * FROM drop_graph('chained', true);
SELECT * FROM drop_graph('VLE', true);
Expand Down
26 changes: 20 additions & 6 deletions src/backend/parser/cypher_analyze.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,20 @@ static bool convert_cypher_walker(Node *node, ParseState *pstate)
* From PG -
* SQLValueFunction - parameterless functions with special grammar
* productions.
* CoerceViaIO - represents a type coercion between two types whose textual
* representations are compatible
* Var - expression node representing a variable (ie, a table column)
* OpExpr - expression node for an operator invocation
* Const - constant value or expression node
* BoolExpr - expression node for the basic Boolean operators AND, OR, NOT
*
* These are a special case that needs to be ignored.
*
* TODO: This likely needs to be done with XmlExpr types, and maybe
* a few others too.
*/
if (IsA(funcexpr, SQLValueFunction))
if (IsA(funcexpr, SQLValueFunction)
|| IsA(funcexpr, CoerceViaIO)
|| IsA(funcexpr, Var) || IsA(funcexpr, OpExpr)
|| IsA(funcexpr, Const) || IsA(funcexpr, BoolExpr))
{
return false;
}
Expand Down Expand Up @@ -315,13 +322,20 @@ static bool is_func_cypher(FuncExpr *funcexpr)
* From PG -
* SQLValueFunction - parameterless functions with special grammar
* productions.
* CoerceViaIO - represents a type coercion between two types whose textual
* representations are compatible
* Var - expression node representing a variable (ie, a table column)
* OpExpr - expression node for an operator invocation
* Const - constant value or expression node
* BoolExpr - expression node for the basic Boolean operators AND, OR, NOT
*
* These are a special case that needs to be ignored.
*
* TODO: This likely needs to be done with XmlExpr types, and maybe
* a few others too.
*/
if (IsA(funcexpr, SQLValueFunction))
if (IsA(funcexpr, SQLValueFunction)
|| IsA(funcexpr, CoerceViaIO)
|| IsA(funcexpr, Var) || IsA(funcexpr, OpExpr)
|| IsA(funcexpr, Const) || IsA(funcexpr, BoolExpr))
{
return false;
}
Expand Down

0 comments on commit 105b78e

Please sign in to comment.