From 05551a556bbca9e4aa5fa910e1b62ea67e6177e6 Mon Sep 17 00:00:00 2001 From: Mergen Imeev <imeevma@tarantool.org> Date: Tue, 12 Dec 2023 13:20:03 +0300 Subject: [PATCH] sql: properly check result of decimal parsing This patch fixes a crash that can occur when SQL parses a decimal literal that represents a number greater than or equal to 10^38. Closes #9469 NO_DOC=bugfix --- .../unreleased/gh-9469-too-big-decimal.md | 4 +++ src/box/errcode.h | 1 + src/box/sql/build.c | 6 +++- src/box/sql/expr.c | 1 + test/box/error.result | 1 + .../gh_9469_too_big_decimals_test.lua | 34 +++++++++++++++++++ 6 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/gh-9469-too-big-decimal.md create mode 100644 test/sql-luatest/gh_9469_too_big_decimals_test.lua diff --git a/changelogs/unreleased/gh-9469-too-big-decimal.md b/changelogs/unreleased/gh-9469-too-big-decimal.md new file mode 100644 index 0000000000..641e4bde22 --- /dev/null +++ b/changelogs/unreleased/gh-9469-too-big-decimal.md @@ -0,0 +1,4 @@ +## bugfix/sql + +* Fixed a crash when a decimal literal representing a decimal number greater + than or equal to 10^38 was parsed in SQL (gh-9469). diff --git a/src/box/errcode.h b/src/box/errcode.h index 05b268f98c..b4489691b5 100644 --- a/src/box/errcode.h +++ b/src/box/errcode.h @@ -329,6 +329,7 @@ struct errcode_record { /*274 */_(ER_UNCONFIGURED, "Please call box.cfg{} first") \ /*275 */_(ER_CREATE_DEFAULT_FUNC, "Failed to create field default function '%s': %s") \ /*276 */_(ER_DEFAULT_FUNC_FAILED, "Error calling field default function '%s': %s") \ + /*277 */_(ER_INVALID_DEC, "Invalid decimal: '%s'") \ /* * !IMPORTANT! Please follow instructions at start of the file diff --git a/src/box/sql/build.c b/src/box/sql/build.c index fa3f2c2a3b..5954d83de2 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -548,7 +548,11 @@ sql_add_term_default(struct Parse *parser, struct ExprSpan *expr_span) const char *str = tt_cstr(expr_span->zStart, expr_span->zEnd - expr_span->zStart); decimal_t val; - decimal_from_string(&val, str); + if (decimal_from_string(&val, str) == NULL) { + diag_set(ClientError, ER_INVALID_DEC, str); + parser->is_aborted = true; + break; + } size = mp_sizeof_decimal(&val); buf = xregion_alloc(region, size); mp_encode_decimal(buf, &val); diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index 4293846c43..be597430a3 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -3159,6 +3159,7 @@ expr_code_dec(struct Parse *parser, struct Expr *expr, bool is_neg, int reg) return; error: sql_xfree(value); + diag_set(ClientError, ER_INVALID_DEC, str); parser->is_aborted = true; } diff --git a/test/box/error.result b/test/box/error.result index e8953d1dc4..c39f3adcc7 100644 --- a/test/box/error.result +++ b/test/box/error.result @@ -495,6 +495,7 @@ t; | 274: box.error.UNCONFIGURED | 275: box.error.CREATE_DEFAULT_FUNC | 276: box.error.DEFAULT_FUNC_FAILED + | 277: box.error.INVALID_DEC | ... test_run:cmd("setopt delimiter ''"); diff --git a/test/sql-luatest/gh_9469_too_big_decimals_test.lua b/test/sql-luatest/gh_9469_too_big_decimals_test.lua new file mode 100644 index 0000000000..c433a7bfc0 --- /dev/null +++ b/test/sql-luatest/gh_9469_too_big_decimals_test.lua @@ -0,0 +1,34 @@ +local server = require('luatest.server') +local t = require('luatest') + +local g = t.group() + +g.before_all(function() + g.server = server:new({alias = 'master'}) + g.server:start() +end) + +g.after_all(function() + g.server:stop() +end) + +g.test_too_big_decimal = function() + g.server:exec(function() + local dec = '111111111111111111111111111111111111111.0' + local sql = ([[SELECT %s;]]):format(dec) + local exp = ([[Invalid decimal: '%s']]):format(dec) + local res, err = box.execute(sql) + t.assert(res == nil) + t.assert_equals(err.message, exp) + + sql = ([[SELECT -%s;]]):format(dec) + res, err = box.execute(sql) + t.assert(res == nil) + t.assert_equals(err.message, exp) + + sql = ([[CREATE TABLE T(i DEC PRIMARY KEY DEFAULT(%s);]]):format(dec) + res, err = box.execute(sql) + t.assert(res == nil) + t.assert_equals(err.message, exp) + end) +end -- GitLab