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 0000000000000000000000000000000000000000..641e4bde22079d951beed8158429e9e8f377ef8b --- /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 05b268f98cf20db5c6fc6d656ff6d1988fef25de..b4489691b5a0bac39f3375c7802088f71ce2d192 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 fa3f2c2a3b317e946beb70cfc19ceb7a81813a9c..5954d83de22fdd606f41210544f89ec87485ce95 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 4293846c43aee87e4ff03488acbfa390e233e26c..be597430a3824715a08fb0277a54d6e1bc51ea8e 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 e8953d1dc4efadd2a685e2ab2a9ae63b43cee22d..c39f3adcc72b9af5cc18b19778adeaf477405e4c 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 0000000000000000000000000000000000000000..c433a7bfc062ad181924e7eaa932d414dad602cd --- /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