From: Mergen Imeev via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: tsafin@tarantool.org Cc: tarantool-patches@dev.tarantool.org Subject: [Tarantool-patches] [PATCH v2 2/3] sql: disallow explicit cast of VARBINARY to number Date: Fri, 30 Jul 2021 10:11:53 +0300 [thread overview] Message-ID: <29442712261cc7c4843352e6d342856ff1106506.1627628984.git.imeevma@gmail.com> (raw) In-Reply-To: <cover.1627628984.git.imeevma@gmail.com> This patch removes explicit cast of VARBINARY values to numeric types. Part of #4470 Closes #4772 Closes #5852 --- src/box/sql/mem.c | 33 ++++--- test/sql-tap/cast.test.lua | 89 +++++++++++++------ ...-4766-wrong-cast-from-blob-to-int.test.lua | 40 --------- test/sql-tap/numcast.test.lua | 18 +--- 4 files changed, 77 insertions(+), 103 deletions(-) delete mode 100755 test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c index 8f56cd289..985438663 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -735,9 +735,9 @@ bin_to_uuid(struct Mem *mem) } static inline int -bytes_to_int(struct Mem *mem) +str_to_int(struct Mem *mem) { - assert((mem->type & (MEM_TYPE_STR | MEM_TYPE_BIN)) != 0); + assert(mem->type == MEM_TYPE_STR); bool is_neg; int64_t i; if (sql_atoi64(mem->z, &i, &is_neg, mem->n) != 0) @@ -747,9 +747,9 @@ bytes_to_int(struct Mem *mem) } static inline int -bytes_to_uint(struct Mem *mem) +str_to_uint(struct Mem *mem) { - assert((mem->type & (MEM_TYPE_STR | MEM_TYPE_BIN)) != 0); + assert(mem->type == MEM_TYPE_STR); bool is_neg; int64_t i; if (sql_atoi64(mem->z, &i, &is_neg, mem->n) != 0) @@ -761,9 +761,9 @@ bytes_to_uint(struct Mem *mem) } static inline int -bytes_to_double(struct Mem *mem) +str_to_double(struct Mem *mem) { - assert((mem->type & (MEM_TYPE_STR | MEM_TYPE_BIN)) != 0); + assert(mem->type == MEM_TYPE_STR); double d; if (sqlAtoF(mem->z, &d, mem->n) == 0) return -1; @@ -905,8 +905,8 @@ mem_to_int(struct Mem *mem) assert(mem->type < MEM_TYPE_INVALID); if ((mem->type & (MEM_TYPE_INT | MEM_TYPE_UINT)) != 0) return 0; - if ((mem->type & (MEM_TYPE_STR | MEM_TYPE_BIN)) != 0) - return bytes_to_int(mem); + if (mem->type == MEM_TYPE_STR) + return str_to_int(mem); if (mem->type == MEM_TYPE_DOUBLE) return double_to_int(mem); return -1; @@ -919,7 +919,7 @@ mem_to_int_precise(struct Mem *mem) if ((mem->type & (MEM_TYPE_INT | MEM_TYPE_UINT)) != 0) return 0; if (mem->type == MEM_TYPE_STR) - return bytes_to_int(mem); + return str_to_int(mem); if (mem->type == MEM_TYPE_DOUBLE) return double_to_int_precise(mem); return -1; @@ -934,7 +934,7 @@ mem_to_double(struct Mem *mem) if ((mem->type & (MEM_TYPE_INT | MEM_TYPE_UINT)) != 0) return int_to_double(mem); if (mem->type == MEM_TYPE_STR) - return bytes_to_double(mem); + return str_to_double(mem); return -1; } @@ -944,10 +944,10 @@ mem_to_number(struct Mem *mem) assert(mem->type < MEM_TYPE_INVALID); if (mem_is_num(mem)) return 0; - if ((mem->type & (MEM_TYPE_STR | MEM_TYPE_BIN)) != 0) { - if (bytes_to_int(mem) == 0) + if (mem->type == MEM_TYPE_STR) { + if (str_to_int(mem) == 0) return 0; - return bytes_to_double(mem); + return str_to_double(mem); } return -1; } @@ -1021,8 +1021,7 @@ mem_cast_explicit(struct Mem *mem, enum field_type type) case MEM_TYPE_UINT: return 0; case MEM_TYPE_STR: - case MEM_TYPE_BIN: - return bytes_to_uint(mem); + return str_to_uint(mem); case MEM_TYPE_DOUBLE: return double_to_uint(mem); default: @@ -1158,7 +1157,7 @@ mem_cast_implicit_old(struct Mem *mem, enum field_type type) if (mem->type == MEM_TYPE_DOUBLE) return double_to_uint_precise(mem); if (mem->type == MEM_TYPE_STR) - return bytes_to_uint(mem); + return str_to_uint(mem); return -1; case FIELD_TYPE_STRING: if ((mem->type & (MEM_TYPE_STR | MEM_TYPE_BIN)) != 0) @@ -1182,7 +1181,7 @@ mem_cast_implicit_old(struct Mem *mem, enum field_type type) if ((mem->type & (MEM_TYPE_INT | MEM_TYPE_UINT)) != 0) return 0; if (mem->type == MEM_TYPE_STR) - return bytes_to_int(mem); + return str_to_int(mem); if (mem->type == MEM_TYPE_DOUBLE) return double_to_int_precise(mem); return -1; diff --git a/test/sql-tap/cast.test.lua b/test/sql-tap/cast.test.lua index 3dc49c38e..997298693 100755 --- a/test/sql-tap/cast.test.lua +++ b/test/sql-tap/cast.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool local test = require("sqltester") -test:plan(91) +test:plan(94) --!./tcltestrunner.lua -- 2005 June 25 @@ -565,23 +565,23 @@ test:do_catchsql_test( -- </case-1.66> }) -test:do_execsql_test( +test:do_catchsql_test( "case-1.68", [[ SELECT CAST(x'31' AS NUMBER) ]], { -- <case-1.68> - 1.0 + 1, "Type mismatch: can not convert varbinary(x'31') to number" -- </case-1.68> }) -test:do_execsql_test( +test:do_catchsql_test( "case-1.69", [[ SELECT typeof(CAST(x'31' AS NUMBER)) ]], { -- <case-1.69> - "number" + 1, "Type mismatch: can not convert varbinary(x'31') to number" -- </case-1.69> }) @@ -727,49 +727,61 @@ test:do_execsql_test( if true then --test:execsql("PRAGMA encoding")[1][1]=="UTF-8" then - test:do_execsql_test( + test:do_catchsql_test( "cast-3.21", [[ SELECT CAST(x'39323233333732303336383534373734383030' AS integer) ]], { -- <cast-3.21> - 9223372036854774800LL + 1, "Type mismatch: can not convert ".. + "varbinary(x'39323233333732303336383534373734383030') to integer" -- </cast-3.21> }) - test:do_execsql_test( + test:do_catchsql_test( "cast-3.22", [[ SELECT CAST(x'393232333337323033363835343737343830302E' AS NUMBER) ]], { -- <cast-3.22> - 9223372036854774784 + 1, "Type mismatch: can not convert ".. + "varbinary(x'393232333337323033363835343737343830302E') ".. + "to number" -- </cast-3.22> }) - test:do_execsql_test( + test:do_catchsql_test( "cast-3.24", [[ SELECT CAST(CAST(x'39323233333732303336383534373734383030' AS NUMBER) AS integer) ]], { -- <cast-3.24> - 9223372036854774800LL + 1, "Type mismatch: can not convert ".. + "varbinary(x'39323233333732303336383534373734383030') to number" -- </cast-3.24> }) end -test:do_execsql_test( +test:do_catchsql_test( "case-3.25", [[ SELECT CAST(x'31383434363734343037333730393535313631352E' AS NUMBER); - ]], { 1.844674407371e+19 } ) + ]], { + 1, "Type mismatch: can not convert ".. + "varbinary(x'31383434363734343037333730393535313631352E') to number" + }) -test:do_execsql_test( +test:do_catchsql_test( "case-3.26", [[ SELECT CAST(x'3138343436373434303733373039353531363135' AS INT); - ]], { 18446744073709551615LL } ) + ]], { + -- <cast-3.21> + 1, "Type mismatch: can not convert ".. + "varbinary(x'3138343436373434303733373039353531363135') to integer" + -- </cast-3.21> + }) test:do_execsql_test( "case-3.31", @@ -863,20 +875,6 @@ test:do_test( -- </cast-4.4> }) - --- gh-4356: Check that result of blob to number cast if of type --- number. --- -test:do_execsql_test( - "cast-5.1", - [[ - SELECT CAST(x'3138343436373434303733372e33' AS NUMBER) - ]], { - -- <cast-5.1> - 184467440737.3 - -- </cast-5.1> - }) - -- gh-4470: Make explicit casts work according to our rules. -- Make sure that explicit cast from BOOLEAN to numeric types throws an error. @@ -977,4 +975,37 @@ test:do_catchsql_test( 1, "Type mismatch: can not convert integer(1) to boolean" }) +-- Make sure that explicit cast from VARBINARY to numeric types throws an error. +test:do_catchsql_test( + "cast-7.1.1", + [[ + SELECT CAST(x'31' AS UNSIGNED); + ]], { + 1, "Type mismatch: can not convert varbinary(x'31') to unsigned" + }) + +test:do_catchsql_test( + "cast-7.1.2", + [[ + SELECT CAST(x'31' AS INTEGER); + ]], { + 1, "Type mismatch: can not convert varbinary(x'31') to integer" + }) + +test:do_catchsql_test( + "cast-7.1.3", + [[ + SELECT CAST(x'31' AS DOUBLE); + ]], { + 1, "Type mismatch: can not convert varbinary(x'31') to double" + }) + +test:do_catchsql_test( + "cast-7.1.4", + [[ + SELECT CAST(x'31' AS NUMBER); + ]], { + 1, "Type mismatch: can not convert varbinary(x'31') to number" + }) + test:finish_test() diff --git a/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua b/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua deleted file mode 100755 index a8cc0e770..000000000 --- a/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env tarantool -local test = require("sqltester") -test:plan(3) - --- --- Make sure that a blob as part of a tuple can be cast to NUMBER, --- INTEGER and UNSIGNED. Prior to this patch, an error could --- appear due to the absence of '\0' at the end of the BLOB. --- -test:do_execsql_test( - "gh-4766-1", - [[ - CREATE TABLE t1 (a VARBINARY PRIMARY KEY); - INSERT INTO t1 VALUES (X'33'), (X'372020202020'); - SELECT a, CAST(a AS NUMBER), CAST(a AS INTEGER), CAST(a AS UNSIGNED) FROM t1; - ]], { - '3', 3, 3, 3, '7 ', 7, 7, 7 - }) - --- --- Make sure that BLOB longer than 12287 bytes cannot be cast to --- INTEGER. --- -local long_str = string.rep('0', 12284) -test:do_execsql_test( - "gh-4766-2", - "SELECT CAST('" .. long_str .. "123'" .. " AS INTEGER);", { - 123 - }) - - -test:do_catchsql_test( - "gh-4766-3", - "SELECT CAST('" .. long_str .. "1234'" .. " AS INTEGER);", { - 1, "Type mismatch: can not convert string('0000000000000000000000000" .. - "0000000000000000000000000000000000000000000000000000000000000000000" .. - "000000000000000000000000000000000000...) to integer" - }) - -test:finish_test() diff --git a/test/sql-tap/numcast.test.lua b/test/sql-tap/numcast.test.lua index 20aea3c4b..802fe712c 100755 --- a/test/sql-tap/numcast.test.lua +++ b/test/sql-tap/numcast.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool local test = require("sqltester") -test:plan(32) +test:plan(30) --!./tcltestrunner.lua -- 2013 March 20 @@ -149,22 +149,6 @@ test:do_execsql_test( -- gh-4233: Make sure that NUMBER can contain UNSIGNED, INTEGER -- and DOUBLE and is not automatically converted to DOUBLE. -- -test:do_execsql_test( - "numcast-3.1", - [[ - SELECT CAST(x'3131313131313131313131313131313131313131' AS NUMBER); - ]], { - 11111111111111111111ULL - }) - -test:do_execsql_test( - "numcast-3.2", - [[ - SELECT CAST(x'31313131313131313131313131313131313131312E' AS NUMBER); - ]], { - 11111111111111110656 - }) - test:do_execsql_test( "numcast-3.3", [[ -- 2.25.1
next prev parent reply other threads:[~2021-07-30 7:12 UTC|newest] Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-07-30 7:11 [Tarantool-patches] [PATCH v2 0/3] Fix explicit casts Mergen Imeev via Tarantool-patches 2021-07-30 7:11 ` [Tarantool-patches] [PATCH v2 1/3] sql: disallow explicit cast of BOOLEAN to number Mergen Imeev via Tarantool-patches 2021-07-30 7:11 ` Mergen Imeev via Tarantool-patches [this message] 2021-07-30 7:11 ` [Tarantool-patches] [PATCH v2 3/3] sql: fix STRING to BOOLEAN explicit cast Mergen Imeev via Tarantool-patches -- strict thread matches above, loose matches on Subject: below -- 2021-08-04 8:32 [Tarantool-patches] [PATCH v2 0/3] Fix explicit casts Mergen Imeev via Tarantool-patches 2021-08-04 8:32 ` [Tarantool-patches] [PATCH v2 2/3] sql: disallow explicit cast of VARBINARY to number Mergen Imeev via Tarantool-patches 2021-08-02 17:25 [Tarantool-patches] [PATCH v2 0/3] Fix explicit casts Mergen Imeev via Tarantool-patches 2021-08-02 17:25 ` [Tarantool-patches] [PATCH v2 2/3] sql: disallow explicit cast of VARBINARY to number Mergen Imeev via Tarantool-patches 2021-07-27 11:31 [Tarantool-patches] [PATCH v2 0/3] Fix explicit casts Mergen Imeev via Tarantool-patches 2021-07-27 11:31 ` [Tarantool-patches] [PATCH v2 2/3] sql: disallow explicit cast of VARBINARY to number Mergen Imeev via Tarantool-patches 2021-07-29 20:58 ` Vladislav Shpilevoy via Tarantool-patches
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=29442712261cc7c4843352e6d342856ff1106506.1627628984.git.imeevma@gmail.com \ --to=tarantool-patches@dev.tarantool.org \ --cc=imeevma@tarantool.org \ --cc=tsafin@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v2 2/3] sql: disallow explicit cast of VARBINARY to number' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox