From 5865f4534910501acd98349ecd0fb011b33b1b1f Mon Sep 17 00:00:00 2001 From: Riya Jain <75467028+riyajain39@users.noreply.github.com> Date: Fri, 20 Oct 2023 14:18:00 +0530 Subject: [PATCH] Fix for the crash in pre_transform_target_entry (#1931) This pull request fix the crash is `pre_transform_target_entry` for queries that involves DELETE ... OUTPUT with JOIN statement. For the delete queries with join statement, the `res->location` will be passed zero. This causes server to crash as the value of `last_dot` pointer has never been computed. This commit implements a check which first computed whether the `res->location` is correct or not and then further proceed to find original identifier. Task: BABEL-4484 Signed-off-by: Riya Jain --- contrib/babelfishpg_tsql/src/hooks.c | 18 +++++++------ test/JDBC/expected/BABEL-4484-vu-cleanup.out | 8 ++++++ test/JDBC/expected/BABEL-4484-vu-prepare.out | 8 ++++++ test/JDBC/expected/BABEL-4484-vu-verify.out | 28 ++++++++++++++++++++ test/JDBC/input/BABEL-4484-vu-cleanup.sql | 8 ++++++ test/JDBC/input/BABEL-4484-vu-prepare.sql | 8 ++++++ test/JDBC/input/BABEL-4484-vu-verify.sql | 11 ++++++++ test/JDBC/upgrade/latest/schedule | 1 + 8 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 test/JDBC/expected/BABEL-4484-vu-cleanup.out create mode 100644 test/JDBC/expected/BABEL-4484-vu-prepare.out create mode 100644 test/JDBC/expected/BABEL-4484-vu-verify.out create mode 100644 test/JDBC/input/BABEL-4484-vu-cleanup.sql create mode 100644 test/JDBC/input/BABEL-4484-vu-prepare.sql create mode 100644 test/JDBC/input/BABEL-4484-vu-verify.sql diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 62815466fb..eb82f8699c 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -1606,7 +1606,7 @@ pre_transform_target_entry(ResTarget *res, ParseState *pstate, if (exprKind == EXPR_KIND_SELECT_TARGET) { int alias_len = 0; - const char *colname_start; + const char *colname_start = NULL; const char *identifier_name = NULL; int open_square_bracket = 0; int double_quotes = 0; @@ -1620,10 +1620,11 @@ pre_transform_target_entry(ResTarget *res, ParseState *pstate, /* * If no alias is specified on a ColumnRef, then get the length of * the name from the ColumnRef and copy the column name from the - * sourcetext + * sourcetext. To prevent the server crash, res->location for queries + * with join statement should not be zero. */ - if (list_length(cref->fields) == 1 && - IsA(linitial(cref->fields), String)) + if (res->location != 0 && (list_length(cref->fields) == 1 && + IsA(linitial(cref->fields), String))) { identifier_name = strVal(linitial(cref->fields)); alias_len = strlen(identifier_name); @@ -1644,13 +1645,14 @@ pre_transform_target_entry(ResTarget *res, ParseState *pstate, * Case 3: Handle the case when column name is delimited with sqb. When number of sqb * are zero, it means we are out of sqb. */ - if(list_length(cref->fields) > 1 && - IsA(llast(cref->fields), String)) + else if(res->location != 0 && (list_length(cref->fields) > 1 && + IsA(llast(cref->fields), String))) { identifier_name = strVal(llast(cref->fields)); alias_len = strlen(identifier_name); colname_start = pstate->p_sourcetext + res->location; - while(true) + last_dot = colname_start; + while(*colname_start != '\0') { if(open_square_bracket == 0 && *colname_start == '"') { @@ -1721,7 +1723,7 @@ pre_transform_target_entry(ResTarget *res, ParseState *pstate, int actual_alias_len = 0; /* To handle queries like SELECT (()) from */ - while(*colname_start == '(' || scanner_isspace(*colname_start)) + while(*colname_start != '\0' && (*colname_start == '(' || scanner_isspace(*colname_start))) { colname_start++; } diff --git a/test/JDBC/expected/BABEL-4484-vu-cleanup.out b/test/JDBC/expected/BABEL-4484-vu-cleanup.out new file mode 100644 index 0000000000..01ba0a9be5 --- /dev/null +++ b/test/JDBC/expected/BABEL-4484-vu-cleanup.out @@ -0,0 +1,8 @@ +DROP TABLE test_babel_4484_t1; +GO + +DROP TABLE test_babel_4484_t2; +GO + +DROP TABLE test_babel_4484_t3; +GO diff --git a/test/JDBC/expected/BABEL-4484-vu-prepare.out b/test/JDBC/expected/BABEL-4484-vu-prepare.out new file mode 100644 index 0000000000..81bcc1e47b --- /dev/null +++ b/test/JDBC/expected/BABEL-4484-vu-prepare.out @@ -0,0 +1,8 @@ +CREATE TABLE test_babel_4484_t1(ABC int, ced varchar(10)); +GO + +CREATE TABLE test_babel_4484_t2(ABC int, 您您 varchar(10)); +GO + +CREATE TABLE test_babel_4484_t3(ABC int, 您您对您对您对您对您对您对您对您对您对您您您 int); +GO diff --git a/test/JDBC/expected/BABEL-4484-vu-verify.out b/test/JDBC/expected/BABEL-4484-vu-verify.out new file mode 100644 index 0000000000..b3961349aa --- /dev/null +++ b/test/JDBC/expected/BABEL-4484-vu-verify.out @@ -0,0 +1,28 @@ +SELECT set_config('babelfishpg_tsql.enable_sll_parse_mode', 'true', false); +GO +~~START~~ +text +on +~~END~~ + + +DELETE test_babel_4484_t1 OUTPUT test_babel_4484_t1.ced FROM test_babel_4484_t1 INNER JOIN test_babel_4484_t2 ON test_babel_4484_t1.ABC = test_babel_4484_t2.ABC WHERE test_babel_4484_t1.ABC = 1; +GO +~~START~~ +varchar +~~END~~ + + +DELETE test_babel_4484_t2 OUTPUT test_babel_4484_t2.您您 FROM test_babel_4484_t2 INNER JOIN test_babel_4484_t3 ON test_babel_4484_t2.ABC = test_babel_4484_t3.ABC WHERE test_babel_4484_t2.ABC = 1; +GO +~~START~~ +varchar +~~END~~ + + +SELECT test_babel_4484_t1.ced FROM test_babel_4484_t1 INNER JOIN test_babel_4484_t2 ON test_babel_4484_t1.ABC = test_babel_4484_t2.ABC WHERE test_babel_4484_t1.ABC = 1; +GO +~~START~~ +varchar +~~END~~ + diff --git a/test/JDBC/input/BABEL-4484-vu-cleanup.sql b/test/JDBC/input/BABEL-4484-vu-cleanup.sql new file mode 100644 index 0000000000..01ba0a9be5 --- /dev/null +++ b/test/JDBC/input/BABEL-4484-vu-cleanup.sql @@ -0,0 +1,8 @@ +DROP TABLE test_babel_4484_t1; +GO + +DROP TABLE test_babel_4484_t2; +GO + +DROP TABLE test_babel_4484_t3; +GO diff --git a/test/JDBC/input/BABEL-4484-vu-prepare.sql b/test/JDBC/input/BABEL-4484-vu-prepare.sql new file mode 100644 index 0000000000..81bcc1e47b --- /dev/null +++ b/test/JDBC/input/BABEL-4484-vu-prepare.sql @@ -0,0 +1,8 @@ +CREATE TABLE test_babel_4484_t1(ABC int, ced varchar(10)); +GO + +CREATE TABLE test_babel_4484_t2(ABC int, 您您 varchar(10)); +GO + +CREATE TABLE test_babel_4484_t3(ABC int, 您您对您对您对您对您对您对您对您对您对您您您 int); +GO diff --git a/test/JDBC/input/BABEL-4484-vu-verify.sql b/test/JDBC/input/BABEL-4484-vu-verify.sql new file mode 100644 index 0000000000..5c5f6a2e63 --- /dev/null +++ b/test/JDBC/input/BABEL-4484-vu-verify.sql @@ -0,0 +1,11 @@ +SELECT set_config('babelfishpg_tsql.enable_sll_parse_mode', 'true', false); +GO + +DELETE test_babel_4484_t1 OUTPUT test_babel_4484_t1.ced FROM test_babel_4484_t1 INNER JOIN test_babel_4484_t2 ON test_babel_4484_t1.ABC = test_babel_4484_t2.ABC WHERE test_babel_4484_t1.ABC = 1; +GO + +DELETE test_babel_4484_t2 OUTPUT test_babel_4484_t2.您您 FROM test_babel_4484_t2 INNER JOIN test_babel_4484_t3 ON test_babel_4484_t2.ABC = test_babel_4484_t3.ABC WHERE test_babel_4484_t2.ABC = 1; +GO + +SELECT test_babel_4484_t1.ced FROM test_babel_4484_t1 INNER JOIN test_babel_4484_t2 ON test_babel_4484_t1.ABC = test_babel_4484_t2.ABC WHERE test_babel_4484_t1.ABC = 1; +GO diff --git a/test/JDBC/upgrade/latest/schedule b/test/JDBC/upgrade/latest/schedule index 42143cbd27..8b078d6380 100644 --- a/test/JDBC/upgrade/latest/schedule +++ b/test/JDBC/upgrade/latest/schedule @@ -473,3 +473,4 @@ sys_asymmetric_keys sys_certificates sys_database_permissions BABEL-4279 +BABEL-4484