diff --git a/changelogs/unreleased/gh-6766-fix-error-in-extension-via-netbox.md b/changelogs/unreleased/gh-6766-fix-error-in-extension-via-netbox.md new file mode 100644 index 0000000000000000000000000000000000000000..44aec1c7bff9274884627df4ab104cdbebd0f488 --- /dev/null +++ b/changelogs/unreleased/gh-6766-fix-error-in-extension-via-netbox.md @@ -0,0 +1,3 @@ +## bugfix/sql + +* Fixed assertion or segfault when MP_EXT received via net.box (gh-6766). diff --git a/src/box/bind.c b/src/box/bind.c index aff2d3d76dcaf9169a6a622329f41b97fbc5ab24..6b7f9365dc6c7355ea4b142b140cf3ff8b723c25 100644 --- a/src/box/bind.c +++ b/src/box/bind.c @@ -34,6 +34,9 @@ #include "sql/sqlInt.h" #include "sql/sqlLimit.h" #include "sql/vdbe.h" +#include "mp_datetime.h" +#include "mp_decimal.h" +#include "mp_uuid.h" const char * sql_bind_name(const struct sql_bind *bind) @@ -99,9 +102,41 @@ sql_bind_decode(struct sql_bind *bind, int i, const char **packet) case MP_BIN: bind->s = mp_decode_bin(packet, &bind->bytes); break; + case MP_EXT: { + int8_t ext_type; + uint32_t size = mp_decode_extl(packet, &ext_type); + switch (ext_type) { + case MP_UUID: + if (uuid_unpack(packet, size, &bind->uuid) == NULL) { + diag_set(ClientError, ER_INVALID_MSGPACK, + "Invalid MP_UUID MsgPack format"); + return -1; + } + break; + case MP_DECIMAL: + if (decimal_unpack(packet, size, &bind->dec) == NULL) { + diag_set(ClientError, ER_INVALID_MSGPACK, + "Invalid MP_DECIMAL MsgPack format"); + return -1; + } + break; + case MP_DATETIME: + if (datetime_unpack(packet, size, &bind->dt) == NULL) { + diag_set(ClientError, ER_INVALID_MSGPACK, + "Invalid MP_DATETIME MsgPack format"); + return -1; + } + break; + default: + diag_set(ClientError, ER_SQL_BIND_TYPE, "USERDATA", + sql_bind_name(bind)); + return -1; + } + bind->ext_type = ext_type; + break; + } case MP_ARRAY: case MP_MAP: - case MP_EXT: bind->s = *packet; mp_next(packet); bind->bytes = *packet - bind->s; diff --git a/test/sql-luatest/gh_6766_mp_ext_via_netbox_test.lua b/test/sql-luatest/gh_6766_mp_ext_via_netbox_test.lua new file mode 100644 index 0000000000000000000000000000000000000000..9ea357ef1eb4b17fa19288b517908ae925aa86c1 --- /dev/null +++ b/test/sql-luatest/gh_6766_mp_ext_via_netbox_test.lua @@ -0,0 +1,44 @@ +local server = require('test.luatest_helpers.server') +local t = require('luatest') +local g = t.group() + +g.before_all(function() + g.server = server:new({alias = 'gh-6766'}) + g.server:start() +end) + +g.after_all(function() + g.server:stop() +end) + +g.test_6766_1 = function() + local conn = g.server.net_box + local val = require('uuid').new() + local res = {{'uuid'}} + local rows = conn:execute([[SELECT typeof(?);]], {val}).rows + t.assert_equals(rows, res) +end + +g.test_6766_2 = function() + local conn = g.server.net_box + local val = require('decimal').new(1.5) + local res = {{'decimal'}} + local rows = conn:execute([[SELECT typeof(?);]], {val}).rows + t.assert_equals(rows, res) +end + +g.test_6766_3 = function() + local conn = g.server.net_box + local val = require('datetime').now() + local res = {{'datetime'}} + local rows = conn:execute([[SELECT typeof(?);]], {val}).rows + t.assert_equals(rows, res) +end + +g.test_6766_4 = function() + local conn = g.server.net_box + local val = require('msgpack').object_from_raw('\xc7\x00\x0f') + local res = "Bind value type USERDATA for parameter 1 is not supported" + local _, err = pcall(conn.execute, conn, [[SELECT typeof(?);]], {val}) + t.assert_equals(err.message, res) +end