From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id EAD2C26681 for ; Fri, 25 Jan 2019 05:50:58 -0500 (EST) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id tFm27WyBYbpZ for ; Fri, 25 Jan 2019 05:50:58 -0500 (EST) Received: from smtp46.i.mail.ru (smtp46.i.mail.ru [94.100.177.106]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id F353D26661 for ; Fri, 25 Jan 2019 05:50:57 -0500 (EST) From: Stanislav Zudin Subject: [tarantool-patches] [PATCH] sql: do not let VALUES statement treat the type definition keywords as values Date: Fri, 25 Jan 2019 13:50:31 +0300 Message-Id: <20190125105031.31745-1-szudin@tarantool.org> Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org, korablev@tarantool.org Cc: Stanislav Zudin The "box.sql.execute('values(blob)')" causes an accert in the expression processing, because the parser doesn't distinguish the keyword "BLOB" from the binary value (in the form X'hex'). This fix adds an additional checks in the SQL grammar. Thus the expressions such as "VALUES(BLOB)", "SELECT FLOAT" and so on are treated as a syntax errors. Closes #3888 --- extra/mkkeywordhash.c | 6 +- src/box/sql/parse.y | 11 ++-- test/sql/gh-3888-values-blob-assert.result | 65 ++++++++++++++++++++ test/sql/gh-3888-values-blob-assert.test.lua | 37 +++++++++++ 4 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 test/sql/gh-3888-values-blob-assert.result create mode 100644 test/sql/gh-3888-values-blob-assert.test.lua diff --git a/extra/mkkeywordhash.c b/extra/mkkeywordhash.c index d92b9eeb7..2b21cb863 100644 --- a/extra/mkkeywordhash.c +++ b/extra/mkkeywordhash.c @@ -109,7 +109,7 @@ static Keyword aKeywordTable[] = { { "BEFORE", "TK_BEFORE", TRIGGER, false }, { "BEGIN", "TK_BEGIN", TRIGGER, true }, { "BETWEEN", "TK_BETWEEN", ALWAYS, true }, - { "BLOB", "TK_BLOB", RESERVED, true }, + { "BLOB", "TK_BLOB_KW", RESERVED, true }, { "BY", "TK_BY", ALWAYS, true }, { "CASCADE", "TK_CASCADE", FKEY, false }, { "CASE", "TK_CASE", ALWAYS, true }, @@ -235,12 +235,12 @@ static Keyword aKeywordTable[] = { { "DOUBLE", "TK_DOUBLE", RESERVED, true }, { "ELSEIF", "TK_STANDARD", RESERVED, true }, { "FETCH", "TK_STANDARD", RESERVED, true }, - { "FLOAT", "TK_FLOAT", RESERVED, true }, + { "FLOAT", "TK_FLOAT_KW", RESERVED, true }, { "FUNCTION", "TK_STANDARD", RESERVED, true }, { "GET", "TK_STANDARD", RESERVED, true }, { "GRANT", "TK_STANDARD", RESERVED, true }, { "INT", "TK_INT", RESERVED, true }, - { "INTEGER", "TK_INTEGER", RESERVED, true }, + { "INTEGER", "TK_INTEGER_KW", RESERVED, true }, { "INOUT", "TK_STANDARD", RESERVED, true }, { "INSENSITIVE", "TK_STANDARD", RESERVED, true }, { "ITERATE", "TK_STANDARD", RESERVED, true }, diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y index 0bcf41594..73a324522 100644 --- a/src/box/sql/parse.y +++ b/src/box/sql/parse.y @@ -211,7 +211,7 @@ columnname(A) ::= nm(A) typedef(Y). {sqlite3AddColumn(pParse,&A,&Y);} IGNORE INITIALLY INSTEAD NO MATCH PLAN QUERY KEY OFFSET RAISE RELEASE REPLACE RESTRICT %ifdef SQLITE_OMIT_COMPOUND_SELECT - INTERSECT + INTERSECT %endif SQLITE_OMIT_COMPOUND_SELECT RENAME CTIME_KW IF . @@ -823,12 +823,15 @@ idlist(A) ::= nm(Y). p->affinity = AFFINITY_TEXT; break; case TK_BLOB: + case TK_BLOB_KW: p->affinity = AFFINITY_BLOB; break; case TK_INTEGER: + case TK_INTEGER_KW: p->affinity = AFFINITY_INTEGER; break; case TK_FLOAT: + case TK_FLOAT_KW: p->affinity = AFFINITY_REAL; break; } @@ -1469,7 +1472,7 @@ wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. { /* Primitive types. */ %type typedef {struct type_def} typedef(A) ::= TEXT . { A.type = AFFINITY_TEXT; } -typedef(A) ::= BLOB . { A.type = AFFINITY_BLOB; } +typedef(A) ::= BLOB_KW . { A.type = AFFINITY_BLOB; } typedef(A) ::= DATE . { A.type = AFFINITY_REAL; } typedef(A) ::= TIME . { A.type = AFFINITY_REAL; } typedef(A) ::= DATETIME . { A.type = AFFINITY_REAL; } @@ -1496,8 +1499,8 @@ typedef(A) ::= VARCHAR char_len(B) . { %type number_typedef {struct type_def} typedef(A) ::= number_typedef(A) . -number_typedef(A) ::= FLOAT|REAL|DOUBLE . { A.type = AFFINITY_REAL; } -number_typedef(A) ::= INT|INTEGER . { A.type = AFFINITY_INTEGER; } +number_typedef(A) ::= FLOAT_KW|REAL|DOUBLE . { A.type = AFFINITY_REAL; } +number_typedef(A) ::= INT|INTEGER_KW . { A.type = AFFINITY_INTEGER; } %type number_len_typedef {struct type_def} number_typedef(A) ::= DECIMAL|NUMERIC|NUM number_len_typedef(B) . { diff --git a/test/sql/gh-3888-values-blob-assert.result b/test/sql/gh-3888-values-blob-assert.result new file mode 100644 index 000000000..2e025f156 --- /dev/null +++ b/test/sql/gh-3888-values-blob-assert.result @@ -0,0 +1,65 @@ +-- sql: assertion fault on VALUES #3888 +-- Very simple query leads to assertion fault: +-- +-- box.cfg{} +-- box.sql.execute("values(blob)") +-- Assertion failed: (pExpr->u.zToken[0] == 'x' || pExpr->u.zToken[0] == 'X'), +-- function sqlite3ExprCodeTarget, +-- file /Users/n.pettik/tarantool/src/box/sql/expr.c, line 3759. +-- Abort trap: 6 +-- +test_run = require('test_run').new() +--- +... +engine = test_run:get_cfg('engine') +--- +... +box.sql.execute('pragma sql_default_engine=\''..engine..'\'') +--- +... +-- check 'VALUES' against typedef keywords (should fail) +box.sql.execute('VALUES(blob)') +--- +- error: 'near "blob": syntax error' +... +box.sql.execute('VALUES(float)') +--- +- error: 'near "float": syntax error' +... +-- check 'SELECT' against typedef keywords (should fail) +box.sql.execute('SELECT blob') +--- +- error: 'near "blob": syntax error' +... +box.sql.execute('SELECT float') +--- +- error: 'near "float": syntax error' +... +-- check 'VALUES' against ID (should fail) +box.sql.execute('VALUES(TheColumnName)') +--- +- error: 'no such column: THECOLUMNNAME' +... +-- check 'SELECT' against ID (should fail) +box.sql.execute('SELECT TheColumnName') +--- +- error: 'no such column: THECOLUMNNAME' +... +-- check 'VALUES' well-formed expression (returns value) +box.sql.execute('VALUES(-0.5e-2)') +--- +- - [-0.005] +... +box.sql.execute('SELECT X\'507265766564\'') +--- +- - ['Preved'] +... +-- check 'SELECT' well-formed expression (return value) +box.sql.execute('SELECT 3.14') +--- +- - [3.14] +... +box.sql.execute('SELECT X\'4D6564766564\'') +--- +- - ['Medved'] +... diff --git a/test/sql/gh-3888-values-blob-assert.test.lua b/test/sql/gh-3888-values-blob-assert.test.lua new file mode 100644 index 000000000..dafb73716 --- /dev/null +++ b/test/sql/gh-3888-values-blob-assert.test.lua @@ -0,0 +1,37 @@ +-- sql: assertion fault on VALUES #3888 +-- Very simple query leads to assertion fault: +-- +-- box.cfg{} +-- box.sql.execute("values(blob)") +-- Assertion failed: (pExpr->u.zToken[0] == 'x' || pExpr->u.zToken[0] == 'X'), +-- function sqlite3ExprCodeTarget, +-- file /Users/n.pettik/tarantool/src/box/sql/expr.c, line 3759. +-- Abort trap: 6 +-- +test_run = require('test_run').new() +engine = test_run:get_cfg('engine') +box.sql.execute('pragma sql_default_engine=\''..engine..'\'') + +-- check 'VALUES' against typedef keywords (should fail) +box.sql.execute('VALUES(blob)') +box.sql.execute('VALUES(float)') + +-- check 'SELECT' against typedef keywords (should fail) +box.sql.execute('SELECT blob') +box.sql.execute('SELECT float') + +-- check 'VALUES' against ID (should fail) +box.sql.execute('VALUES(TheColumnName)') + +-- check 'SELECT' against ID (should fail) +box.sql.execute('SELECT TheColumnName') + +-- check 'VALUES' well-formed expression (returns value) +box.sql.execute('VALUES(-0.5e-2)') +box.sql.execute('SELECT X\'507265766564\'') + +-- check 'SELECT' well-formed expression (return value) +box.sql.execute('SELECT 3.14') +box.sql.execute('SELECT X\'4D6564766564\'') + + -- 2.17.1 --- Branch: https://github.com/tarantool/tarantool/tree/sz/gh-3888-values-blob-assert Issue: https://github.com/tarantool/tarantool/issues/3888