mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 19:23:03 +01:00
Don't leak memory after conversion to blob for store the value in a variable or parameter
This commit is contained in:
parent
9c326ffb8b
commit
032a4b170c
@ -2443,10 +2443,6 @@ static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc
|
||||
ULONG blob_temp_id = blob->blb_temp_id;
|
||||
BLB_move(tdbb, &blob_desc, to_desc, field);
|
||||
|
||||
// finish if we're just moving values in descriptors
|
||||
if (!field || field->nod_type != nod_field)
|
||||
return;
|
||||
|
||||
// 14-June-2004. Nickolay Samofatov
|
||||
// The code below saves a lot of memory when bunches of records are
|
||||
// converted to blobs from strings. If BLB_move is materialized blob we
|
||||
@ -2479,9 +2475,14 @@ static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc
|
||||
}
|
||||
else {
|
||||
// But even in bad case when we cannot free blob immediately
|
||||
// we may still bind lifetime of blob to current request.
|
||||
if (!current->bli_request) {
|
||||
current->bli_request = tdbb->tdbb_request;
|
||||
// we may still bind lifetime of blob to current top level request.
|
||||
if (!current->bli_request)
|
||||
{
|
||||
jrd_req* blob_request = tdbb->tdbb_request;
|
||||
while (blob_request->req_caller)
|
||||
blob_request = blob_request->req_caller;
|
||||
|
||||
current->bli_request = blob_request;
|
||||
current->bli_request->req_blobs.add(blob_temp_id);
|
||||
}
|
||||
}
|
||||
|
@ -660,7 +660,8 @@ void EXE_receive(thread_db* tdbb,
|
||||
jrd_req* request,
|
||||
USHORT msg,
|
||||
USHORT length,
|
||||
UCHAR* buffer)
|
||||
UCHAR* buffer,
|
||||
bool top_level)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -738,6 +739,34 @@ void EXE_receive(thread_db* tdbb,
|
||||
else
|
||||
MOVE_FASTER((SCHAR *) request + message->nod_impure, buffer, length);
|
||||
|
||||
// ASF: temporary blobs returned to the client should not be released
|
||||
// with the request, but in the transaction end.
|
||||
if (top_level)
|
||||
{
|
||||
for (int i = 0; i < format->fmt_count; ++i)
|
||||
{
|
||||
const DSC* desc = &format->fmt_desc[i];
|
||||
|
||||
if (desc->isBlob())
|
||||
{
|
||||
const bid* id = (bid*)
|
||||
((UCHAR*)request + message->nod_impure + (ULONG)(IPTR)desc->dsc_address);
|
||||
|
||||
if (transaction->tra_blobs.locate(id->bid_temp_id()))
|
||||
{
|
||||
BlobIndex* current = &transaction->tra_blobs.current();
|
||||
|
||||
if (current->bli_request &&
|
||||
current->bli_request->req_blobs.locate(id->bid_temp_id()))
|
||||
{
|
||||
current->bli_request->req_blobs.fastRemove();
|
||||
current->bli_request = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
execute_looper(tdbb, request, transaction, jrd_req::req_proceed);
|
||||
|
||||
} //try
|
||||
|
@ -35,7 +35,7 @@ namespace Jrd {
|
||||
void EXE_assignment(Jrd::thread_db*, Jrd::jrd_nod*);
|
||||
void EXE_execute_db_triggers(Jrd::thread_db*, Jrd::jrd_tra*, enum Jrd::jrd_req::req_ta);
|
||||
Jrd::jrd_req* EXE_find_request(Jrd::thread_db*, Jrd::jrd_req*, bool);
|
||||
void EXE_receive(Jrd::thread_db*, Jrd::jrd_req*, USHORT, USHORT, UCHAR*);
|
||||
void EXE_receive(Jrd::thread_db*, Jrd::jrd_req*, USHORT, USHORT, UCHAR*, bool = false);
|
||||
void EXE_send(Jrd::thread_db*, Jrd::jrd_req*, USHORT, USHORT, const UCHAR*);
|
||||
void EXE_start(Jrd::thread_db*, Jrd::jrd_req*, Jrd::jrd_tra*);
|
||||
void EXE_unwind(Jrd::thread_db*, Jrd::jrd_req*);
|
||||
|
@ -3179,7 +3179,7 @@ ISC_STATUS GDS_RECEIVE(ISC_STATUS * user_status,
|
||||
#endif
|
||||
|
||||
EXE_receive(tdbb, request, msg_type, msg_length,
|
||||
reinterpret_cast<UCHAR*>(msg));
|
||||
reinterpret_cast<UCHAR*>(msg), true);
|
||||
|
||||
check_autocommit(request, tdbb);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user