From 1f7e7aa2bf47445dffc713df336288676b927445 Mon Sep 17 00:00:00 2001 From: Chris Sosnin <k.sosnin@tarantool.org> Date: Wed, 11 Mar 2020 11:43:22 +0300 Subject: [PATCH] iproto: add an empty body to the unprepare response Absence of the body in the unprepare response forces users to perform additional checks to avoid errors. Adding an empty body fixes this problem. Closes #4769 Reviewed-by: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> Reviewed-by: Nikita Pettik <korablev@tarantool.org> --- src/box/iproto.cc | 17 +++-- .../gh-4769-unprepare-response-body.result | 64 +++++++++++++++++++ .../gh-4769-unprepare-response-body.test.lua | 25 ++++++++ 3 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 test/box/gh-4769-unprepare-response-body.result create mode 100644 test/box/gh-4769-unprepare-response-body.test.lua diff --git a/src/box/iproto.cc b/src/box/iproto.cc index f313af6aec..f31738cb03 100644 --- a/src/box/iproto.cc +++ b/src/box/iproto.cc @@ -1780,21 +1780,24 @@ tx_process_sql(struct cmsg *m) * become out of date during yield. */ out = msg->connection->tx.p_obuf; + if (is_unprepare) { + if (iproto_reply_ok(out, msg->header.sync, schema_version) != 0) + goto error; + iproto_wpos_create(&msg->wpos, out); + return; + } struct obuf_svp header_svp; /* Prepare memory for the iproto header. */ if (iproto_prepare_header(out, &header_svp, IPROTO_HEADER_LEN) != 0) { port_destroy(&port); goto error; } - /* Nothing to dump in case of UNPREPARE request. */ - if (!is_unprepare) { - if (port_dump_msgpack(&port, out) != 0) { - port_destroy(&port); - obuf_rollback_to_svp(out, &header_svp); - goto error; - } + if (port_dump_msgpack(&port, out) != 0) { port_destroy(&port); + obuf_rollback_to_svp(out, &header_svp); + goto error; } + port_destroy(&port); iproto_reply_sql(out, &header_svp, msg->header.sync, schema_version); iproto_wpos_create(&msg->wpos, out); return; diff --git a/test/box/gh-4769-unprepare-response-body.result b/test/box/gh-4769-unprepare-response-body.result new file mode 100644 index 0000000000..96e234b9b1 --- /dev/null +++ b/test/box/gh-4769-unprepare-response-body.result @@ -0,0 +1,64 @@ +-- test-run result file version 2 +net_box = require('net.box') + | --- + | ... +msgpack = require('msgpack') + | --- + | ... +urilib = require('uri') + | --- + | ... + +IPROTO_REQUEST_TYPE = 0x00 + | --- + | ... +IPROTO_PREPARE = 13 + | --- + | ... +IPROTO_SQL_TEXT = 0x40 + | --- + | ... +IPROTO_STMT_ID = 0x43 + | --- + | ... + +box.schema.user.grant('guest', 'read, write, execute', 'universe') + | --- + | ... +uri = urilib.parse(box.cfg.listen) + | --- + | ... +socket = net_box.establish_connection(uri.host, uri.service) + | --- + | ... + +header = { [IPROTO_REQUEST_TYPE] = IPROTO_PREPARE } + | --- + | ... +body = { [IPROTO_SQL_TEXT] = 'SELECT 1' } + | --- + | ... +response = iproto_request(socket, header, body) + | --- + | ... + +body = { [IPROTO_STMT_ID] = response['body'][IPROTO_STMT_ID] } + | --- + | ... +-- Decoding of the response will fail if there's no body. +response = iproto_request(socket, header, body) + | --- + | ... +response.body + | --- + | - {} + | ... + +box.schema.user.revoke('guest', 'read, write, execute', 'universe') + | --- + | ... +socket:close() + | --- + | - true + | ... + diff --git a/test/box/gh-4769-unprepare-response-body.test.lua b/test/box/gh-4769-unprepare-response-body.test.lua new file mode 100644 index 0000000000..9b53022019 --- /dev/null +++ b/test/box/gh-4769-unprepare-response-body.test.lua @@ -0,0 +1,25 @@ +net_box = require('net.box') +msgpack = require('msgpack') +urilib = require('uri') + +IPROTO_REQUEST_TYPE = 0x00 +IPROTO_PREPARE = 13 +IPROTO_SQL_TEXT = 0x40 +IPROTO_STMT_ID = 0x43 + +box.schema.user.grant('guest', 'read, write, execute', 'universe') +uri = urilib.parse(box.cfg.listen) +socket = net_box.establish_connection(uri.host, uri.service) + +header = { [IPROTO_REQUEST_TYPE] = IPROTO_PREPARE } +body = { [IPROTO_SQL_TEXT] = 'SELECT 1' } +response = iproto_request(socket, header, body) + +body = { [IPROTO_STMT_ID] = response['body'][IPROTO_STMT_ID] } +-- Decoding of the response will fail if there's no body. +response = iproto_request(socket, header, body) +response.body + +box.schema.user.revoke('guest', 'read, write, execute', 'universe') +socket:close() + -- GitLab