From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtpng3.m.smailru.net (smtpng3.m.smailru.net [94.100.177.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id D71A6431780 for ; Fri, 21 Aug 2020 11:40:53 +0300 (MSK) From: imeevma@tarantool.org Date: Fri, 21 Aug 2020 11:40:52 +0300 Message-Id: <56f685097fb1120e36bf03114a32d567e668a2a2.1597998754.git.imeevma@gmail.com> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH v1 2/2] sql: remove implicit cast in bitwise operations List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: korablev@tarantool.org, tsafin@tarantool.org Cc: tarantool-patches@dev.tarantool.org This patch removes the implicit conversion from STRING to INTEGER from bitwise operations. However, DOUBLE can still be implicitly converted to INTEGER. Follow-up #3809 --- src/box/sql/vdbe.c | 59 ++++++++++++++++++++++++++++++++--------- test/sql/types.result | 49 ++++++++++++++++++++++++++++++++++ test/sql/types.test.lua | 14 ++++++++++ 3 files changed, 110 insertions(+), 12 deletions(-) diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index c0143a6b1..a8db6d076 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -1989,19 +1989,44 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ pIn1 = &aMem[pOp->p1]; pIn2 = &aMem[pOp->p2]; + enum mp_type type1 = mem_mp_type(pIn1); + enum mp_type type2 = mem_mp_type(pIn2); pOut = vdbe_prepare_null_out(p, pOp->p3); - if ((pIn1->flags | pIn2->flags) & MEM_Null) { + if (type1 == MP_NIL || type2 == MP_NIL) { /* Force NULL be of type INTEGER. */ pOut->field_type = FIELD_TYPE_INTEGER; break; } - bool unused; - if (sqlVdbeIntValue(pIn2, (int64_t *) &iA, &unused) != 0) { + if (type2 == MP_DOUBLE) { + double r = pIn2->u.r; + if (r >= 0 && r < (double)UINT64_MAX) { + iB = (int64_t)(uint64_t)r; + type2 = MP_UINT; + } else if (r >= (double)INT64_MIN && r < 0) { + iB = (int64_t)r; + type2 = MP_INT; + } + } + if (type2 == MP_INT || type2 == MP_UINT) { + iB = pIn2->u.i; + } else { diag_set(ClientError, ER_SQL_TYPE_MISMATCH, sql_value_to_diag_str(pIn2), "integer"); goto abort_due_to_error; } - if (sqlVdbeIntValue(pIn1, (int64_t *) &iB, &unused) != 0) { + if (type1 == MP_DOUBLE) { + double r = pIn1->u.r; + if (r >= 0 && r < (double)UINT64_MAX) { + iA = (int64_t)(uint64_t)r; + type1 = MP_UINT; + } else if (r >= (double)INT64_MIN && r < 0) { + iA = (int64_t)r; + type1 = MP_INT; + } + } + if (type1 == MP_INT || type1 == MP_UINT) { + iA = pIn1->u.i; + } else { diag_set(ClientError, ER_SQL_TYPE_MISMATCH, sql_value_to_diag_str(pIn1), "integer"); goto abort_due_to_error; @@ -2621,19 +2646,29 @@ case OP_Not: { /* same as TK_NOT, in1, out2 */ */ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ pIn1 = &aMem[pOp->p1]; + enum mp_type type = mem_mp_type(pIn1); pOut = vdbe_prepare_null_out(p, pOp->p2); /* Force NULL be of type INTEGER. */ pOut->field_type = FIELD_TYPE_INTEGER; - if ((pIn1->flags & MEM_Null)==0) { - int64_t i; - bool is_neg; - if (sqlVdbeIntValue(pIn1, &i, &is_neg) != 0) { - diag_set(ClientError, ER_SQL_TYPE_MISMATCH, - sql_value_to_diag_str(pIn1), "integer"); - goto abort_due_to_error; + int64_t i; + if (type == MP_DOUBLE) { + double r = pIn1->u.r; + if (r >= 0 && r < (double)UINT64_MAX) { + i = (int64_t)(uint64_t)r; + type = MP_UINT; + } else if (r >= (double)INT64_MIN && r < 0) { + i = (int64_t)r; + type = MP_INT; } - mem_set_i64(pOut, ~i); } + if (type == MP_INT || type == MP_UINT) { + i = pIn1->u.i; + } else { + diag_set(ClientError, ER_SQL_TYPE_MISMATCH, + sql_value_to_diag_str(pIn1), "integer"); + goto abort_due_to_error; + } + mem_set_i64(pOut, ~i); break; } diff --git a/test/sql/types.result b/test/sql/types.result index caedbf409..601e5beca 100644 --- a/test/sql/types.result +++ b/test/sql/types.result @@ -2846,3 +2846,52 @@ box.execute([[SELECT 1 - '2';]]) - null - 'Type mismatch: can not convert 2 to numeric' ... +-- +-- Make sure there is no implicit string-to-number conversion in bitwise +-- operations. +-- +box.execute([[SELECT '1' | 2;]]) +--- +- null +- 'Type mismatch: can not convert 1 to integer' +... +box.execute([[SELECT '1' & 2;]]) +--- +- null +- 'Type mismatch: can not convert 1 to integer' +... +box.execute([[SELECT '1' << 2;]]) +--- +- null +- 'Type mismatch: can not convert 1 to integer' +... +box.execute([[SELECT '1' >> 2;]]) +--- +- null +- 'Type mismatch: can not convert 1 to integer' +... +box.execute([[SELECT ~'1';]]) +--- +- null +- 'Type mismatch: can not convert 1 to integer' +... +box.execute([[SELECT 1 | '2';]]) +--- +- null +- 'Type mismatch: can not convert 2 to integer' +... +box.execute([[SELECT 1 & '2';]]) +--- +- null +- 'Type mismatch: can not convert 2 to integer' +... +box.execute([[SELECT 1 << '2';]]) +--- +- null +- 'Type mismatch: can not convert 2 to integer' +... +box.execute([[SELECT 1 >> '2';]]) +--- +- null +- 'Type mismatch: can not convert 2 to integer' +... diff --git a/test/sql/types.test.lua b/test/sql/types.test.lua index 844a6b670..2d2f41da2 100644 --- a/test/sql/types.test.lua +++ b/test/sql/types.test.lua @@ -638,3 +638,17 @@ box.execute([[SELECT 1 % '2';]]) box.execute([[SELECT 1 * '2';]]) box.execute([[SELECT 1 / '2';]]) box.execute([[SELECT 1 - '2';]]) + +-- +-- Make sure there is no implicit string-to-number conversion in bitwise +-- operations. +-- +box.execute([[SELECT '1' | 2;]]) +box.execute([[SELECT '1' & 2;]]) +box.execute([[SELECT '1' << 2;]]) +box.execute([[SELECT '1' >> 2;]]) +box.execute([[SELECT ~'1';]]) +box.execute([[SELECT 1 | '2';]]) +box.execute([[SELECT 1 & '2';]]) +box.execute([[SELECT 1 << '2';]]) +box.execute([[SELECT 1 >> '2';]]) -- 2.25.1