8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 22:43:03 +01:00

Fixed #8027: Broken gbak statistics

This commit is contained in:
AlexPeshkoff 2024-02-29 18:05:51 +03:00
parent f674c7f53c
commit 210310eab3
3 changed files with 42 additions and 19 deletions

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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.