From 210310eab3a05db89e5fbe398cb45fd7c23bc97c Mon Sep 17 00:00:00 2001 From: AlexPeshkoff Date: Thu, 29 Feb 2024 18:05:51 +0300 Subject: [PATCH] Fixed #8027: Broken gbak statistics --- src/remote/client/interface.cpp | 37 +++++++++++++++++++++++++-------- src/remote/protocol.cpp | 20 +++++++++--------- src/remote/protocol.h | 4 ++++ 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/remote/client/interface.cpp b/src/remote/client/interface.cpp index b814a91ffe..0c7386bec4 100644 --- a/src/remote/client/interface.cpp +++ b/src/remote/client/interface.cpp @@ -124,10 +124,10 @@ namespace { status_exception::raise(Arg::Gds(isc_imp_exc) << Arg::Gds(isc_blktoobig)); } - class SaveString + class UsePreallocatedBuffer { public: - SaveString(cstring& toSave, ULONG newLength, UCHAR* newBuffer) + UsePreallocatedBuffer(cstring& toSave, ULONG newLength, UCHAR* newBuffer) : ptr(&toSave), oldValue(*ptr) { @@ -135,16 +135,30 @@ namespace { ptr->cstr_allocated = newLength; } - ~SaveString() + ~UsePreallocatedBuffer() { *ptr = oldValue; } - private: + protected: cstring* ptr; + private: cstring oldValue; }; + class UseStandardBuffer : public UsePreallocatedBuffer + { + public: + UseStandardBuffer(cstring& toSave) + : UsePreallocatedBuffer(toSave,0, nullptr) + { } + + ~UseStandardBuffer() + { + ptr->free(); + } + }; + class ClientPortsCleanup : public PortsCleanup { public: @@ -4149,7 +4163,7 @@ Statement* Attachment::prepare(CheckStatusWrapper* status, ITransaction* apiTra, } P_RESP* response = &packet->p_resp; - SaveString temp(response->p_resp_data, buffer.getCount(), buffer.begin()); + UsePreallocatedBuffer temp(response->p_resp_data, buffer.getCount(), buffer.begin()); try { @@ -5302,7 +5316,7 @@ int Blob::getSegment(CheckStatusWrapper* status, unsigned int bufferLength, void PACKET* packet = &rdb->rdb_packet; P_SGMT* segment = &packet->p_sgmt; P_RESP* response = &packet->p_resp; - SaveString temp(response->p_resp_data, bufferLength, bufferPtr); + UsePreallocatedBuffer temp(response->p_resp_data, bufferLength, bufferPtr); // Handle a blob that has been created rather than opened (this should yield an error) @@ -7575,6 +7589,9 @@ static void batch_dsql_fetch(rem_port* port, // we need to clear the queue. const bool clear_queue = (id != statement->rsr_id || port->port_type == rem_port::XNET); + // Avoid damaging preallocated buffer for response data + UseStandardBuffer guard(packet->p_resp.p_resp_data); + statement->rsr_flags.set(Rsr::FETCHED); while (true) { @@ -7736,6 +7753,9 @@ static void batch_gds_receive(rem_port* port, clear_queue = true; } + // Avoid damaging preallocated buffer for response data + UseStandardBuffer guard(packet->p_resp.p_resp_data); + // Receive the whole batch of records, until end-of-batch is seen while (true) @@ -8142,7 +8162,7 @@ static void info(CheckStatusWrapper* status, // Set up for the response packet. P_RESP* response = &packet->p_resp; - SaveString temp(response->p_resp_data, buffer_length, buffer); + UsePreallocatedBuffer temp(response->p_resp_data, buffer_length, buffer); receive_response(status, rdb, packet); } @@ -9352,8 +9372,7 @@ static void svcstart(CheckStatusWrapper* status, // Set up for the response packet. P_RESP* response = &packet->p_resp; - SaveString temp(response->p_resp_data, 0, NULL); - response->p_resp_data.cstr_length = 0; + UseStandardBuffer temp(response->p_resp_data); receive_response(status, rdb, packet); } diff --git a/src/remote/protocol.cpp b/src/remote/protocol.cpp index ef466b8f34..1447a593f9 100644 --- a/src/remote/protocol.cpp +++ b/src/remote/protocol.cpp @@ -100,7 +100,6 @@ enum SQL_STMT_TYPE }; static bool alloc_cstring(RemoteXdr*, CSTRING*); -static void free_cstring(RemoteXdr*, CSTRING*); static void reset_statement(RemoteXdr*, SSHORT); static bool_t xdr_cstring(RemoteXdr*, CSTRING*); static bool_t xdr_response(RemoteXdr*, CSTRING*); @@ -1247,7 +1246,7 @@ static bool alloc_cstring(RemoteXdr* xdrs, CSTRING* cstring) if (cstring->cstr_length > cstring->cstr_allocated && cstring->cstr_allocated) { - free_cstring(xdrs, cstring); + cstring->free(xdrs); } if (!cstring->cstr_address) @@ -1268,7 +1267,7 @@ static bool alloc_cstring(RemoteXdr* xdrs, CSTRING* cstring) } -static void free_cstring( RemoteXdr* xdrs, CSTRING* cstring) +void CSTRING::free(RemoteXdr* xdrs) { /************************************** * @@ -1281,14 +1280,15 @@ static void free_cstring( RemoteXdr* xdrs, CSTRING* cstring) * **************************************/ - if (cstring->cstr_allocated) + if (cstr_allocated) { - delete[] cstring->cstr_address; - DEBUG_XDR_FREE(xdrs, cstring, cstring->cstr_address, cstring->cstr_allocated); + delete[] cstr_address; + if (xdrs) + DEBUG_XDR_FREE(xdrs, this, cstr_address, cstr_allocated); } - cstring->cstr_address = NULL; - cstring->cstr_allocated = 0; + cstr_address = NULL; + cstr_allocated = 0; } @@ -1393,7 +1393,7 @@ static bool_t xdr_cstring_with_limit( RemoteXdr* xdrs, CSTRING* cstring, ULONG l return TRUE; case XDR_FREE: - free_cstring(xdrs, cstring); + cstring->free(xdrs); return TRUE; } @@ -1502,7 +1502,7 @@ static bool_t xdr_longs( RemoteXdr* xdrs, CSTRING* cstring) break; case XDR_FREE: - free_cstring(xdrs, cstring); + cstring->free(xdrs); return TRUE; } diff --git a/src/remote/protocol.h b/src/remote/protocol.h index 992ff9bfb0..4c287bcc67 100644 --- a/src/remote/protocol.h +++ b/src/remote/protocol.h @@ -324,11 +324,15 @@ enum P_OP // Count String Structure +class RemoteXdr; + typedef struct cstring { ULONG cstr_length; ULONG cstr_allocated; UCHAR* cstr_address; + + void free(RemoteXdr* xdrs = nullptr); } CSTRING; // CVC: Only used in p_blob, p_sgmt & p_ddl, to validate constness.