From: Mergen Imeev via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: v.shpilevoy@tarantool.org Cc: tarantool-patches@dev.tarantool.org Subject: [Tarantool-patches] [PATCH v1 2/2] sql: disallow explicit cast of VARBINARY to number Date: Wed, 21 Jul 2021 18:10:24 +0300 [thread overview] Message-ID: <d9b817112899bc87dbf2676c10cffe3ba9c9481a.1626880058.git.imeevma@gmail.com> (raw) In-Reply-To: <cover.1626880058.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 | 80 +++++++++++++++---- ...-4766-wrong-cast-from-blob-to-int.test.lua | 40 ---------- test/sql-tap/numcast.test.lua | 10 ++- 4 files changed, 85 insertions(+), 78 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 5c44bfdfc..e75392834 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -736,9 +736,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) @@ -748,9 +748,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) @@ -762,9 +762,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; @@ -906,8 +906,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; @@ -920,7 +920,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; @@ -935,7 +935,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; } @@ -945,10 +945,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; } @@ -1022,8 +1022,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: @@ -1156,7 +1155,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) @@ -1180,7 +1179,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..379fbf09e 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(95) --!./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", @@ -867,13 +879,14 @@ test:do_test( -- gh-4356: Check that result of blob to number cast if of type -- number. -- -test:do_execsql_test( +test:do_catchsql_test( "cast-5.1", [[ SELECT CAST(x'3138343436373434303733372e33' AS NUMBER) ]], { -- <cast-5.1> - 184467440737.3 + 1, "Type mismatch: can not convert ".. + "varbinary(x'3138343436373434303733372E33') to number" -- </cast-5.1> }) @@ -977,4 +990,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 56b11da25..a2877167f 100755 --- a/test/sql-tap/numcast.test.lua +++ b/test/sql-tap/numcast.test.lua @@ -149,20 +149,22 @@ 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( +test:do_catchsql_test( "numcast-3.1", [[ SELECT CAST(x'3131313131313131313131313131313131313131' AS NUMBER); ]], { - 11111111111111111111ULL + 1, "Type mismatch: can not convert ".. + "varbinary(x'3131313131313131313131313131313131313131') to number" }) -test:do_execsql_test( +test:do_catchsql_test( "numcast-3.2", [[ SELECT CAST(x'31313131313131313131313131313131313131312E' AS NUMBER); ]], { - 11111111111111110656 + 1, "Type mismatch: can not convert ".. + "varbinary(x'31313131313131313131313131313131313131312E') to number" }) test:do_execsql_test( -- 2.25.1
next prev parent reply other threads:[~2021-07-21 15:11 UTC|newest] Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-07-21 15:10 [Tarantool-patches] [PATCH v1 0/2] Fix explicit casts Mergen Imeev via Tarantool-patches 2021-07-21 15:10 ` [Tarantool-patches] [PATCH v1 1/2] sql: disallow explicit cast of BOOLEAN to number Mergen Imeev via Tarantool-patches 2021-07-26 20:11 ` Vladislav Shpilevoy via Tarantool-patches 2021-07-21 15:10 ` Mergen Imeev via Tarantool-patches [this message] 2021-07-26 20:12 ` [Tarantool-patches] [PATCH v1 2/2] sql: disallow explicit cast of VARBINARY " 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=d9b817112899bc87dbf2676c10cffe3ba9c9481a.1626880058.git.imeevma@gmail.com \ --to=tarantool-patches@dev.tarantool.org \ --cc=imeevma@tarantool.org \ --cc=v.shpilevoy@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v1 2/2] 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