Skip to content

Commit 749bcc0

Browse files
committed
This should fix #7817: Memory leak is possible for UDF array arguments
1 parent 5e0cfe3 commit 749bcc0

File tree

1 file changed

+28
-36
lines changed

1 file changed

+28
-36
lines changed

src/jrd/fun.epp

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,8 @@ enum UdfError
292292
static SSHORT blob_get_segment(blb*, UCHAR*, USHORT, USHORT*);
293293
static void blob_put_segment(blb*, const UCHAR*, USHORT);
294294
static SLONG blob_lseek(blb*, USHORT, SLONG);
295-
static SLONG get_scalar_array(const Parameter*, DSC*, scalar_array_desc*, UCharStack&);
295+
static ULONG get_scalar_array(thread_db* tdbb, const Parameter*, DSC*,
296+
scalar_array_desc*, UCharStack&);
296297
static void invoke(thread_db* tdbb,
297298
const Function* function,
298299
const Parameter* return_ptr,
@@ -436,8 +437,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
436437

437438
temp_desc = parameter->prm_desc;
438439
temp_desc.dsc_address = temp_ptr;
439-
// CVC: There's a theoretical possibility of overflowing "length" here.
440-
USHORT length = FB_ALIGN(temp_desc.dsc_length, FB_DOUBLE_ALIGN);
440+
ULONG length = FB_ALIGN(temp_desc.dsc_length, FB_DOUBLE_ALIGN);
441441

442442
// If we've got a null argument, just pass zeros (got any better ideas?)
443443

@@ -446,7 +446,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
446446
if (parameter->prm_fun_mechanism == FUN_value)
447447
{
448448
UCHAR* p = (UCHAR *) arg_ptr;
449-
MOVE_CLEAR(p, (SLONG) length);
449+
MOVE_CLEAR(p, length);
450450
p += length;
451451
arg_ptr = reinterpret_cast<UDF_ARG*>(p);
452452
continue;
@@ -458,7 +458,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
458458
}
459459

460460
if (parameter->prm_fun_mechanism != FUN_ref_with_null)
461-
MOVE_CLEAR(temp_ptr, (SLONG) length);
461+
MOVE_CLEAR(temp_ptr, length);
462462
else
463463
{
464464
// Probably for arrays and blobs it's better to preserve the
@@ -468,7 +468,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
468468
case dtype_quad:
469469
case dtype_array:
470470
case dtype_blob:
471-
MOVE_CLEAR(temp_ptr, (SLONG) length);
471+
MOVE_CLEAR(temp_ptr, length);
472472
break;
473473
default: // FUN_ref_with_null, non-blob, non-array: we send null pointer.
474474
*arg_ptr++ = 0;
@@ -478,7 +478,8 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
478478
}
479479
else if (parameter->prm_fun_mechanism == FUN_scalar_array)
480480
{
481-
length = get_scalar_array(parameter, input, (scalar_array_desc*)temp_ptr, array_stack);
481+
length = get_scalar_array(tdbb, parameter, input, (scalar_array_desc*) temp_ptr,
482+
array_stack);
482483
}
483484
else
484485
{
@@ -975,10 +976,11 @@ static SSHORT blob_get_segment(blb* blob, UCHAR* buffer, USHORT length, USHORT*
975976
}
976977

977978

978-
static SLONG get_scalar_array(const Parameter* arg,
979-
DSC* value,
980-
scalar_array_desc* scalar_desc,
981-
UCharStack& stack)
979+
static ULONG get_scalar_array(thread_db* tdbb,
980+
const Parameter* arg,
981+
DSC* value,
982+
scalar_array_desc* scalar_desc,
983+
UCharStack& stack)
982984
{
983985
/**************************************
984986
*
@@ -992,17 +994,16 @@ static SLONG get_scalar_array(const Parameter* arg,
992994
* Return length of array desc.
993995
*
994996
**************************************/
995-
thread_db* tdbb = JRD_get_thread_data();
997+
MemoryPool& pool = *tdbb->getDefaultPool();
996998

997999
// Get first the array descriptor, then the array
9981000

9991001
SLONG stuff[IAD_LEN(16) / 4];
10001002
Ods::InternalArrayDesc* array_desc = (Ods::InternalArrayDesc*) stuff;
1001-
blb* blob = blb::get_array(tdbb, tdbb->getRequest()->req_transaction, (bid*)value->dsc_address,
1002-
array_desc);
1003+
blb* blob = blb::get_array(tdbb, tdbb->getRequest()->req_transaction,
1004+
(bid*) value->dsc_address, array_desc);
10031005

1004-
fb_assert(array_desc->iad_total_length >= 0); // check before upcasting to size_t
1005-
UCHAR* data = FB_NEW_POOL(*getDefaultMemoryPool()) UCHAR[static_cast<size_t>(array_desc->iad_total_length)];
1006+
AutoPtr<UCHAR, ArrayDelete> data(FB_NEW_POOL(pool) UCHAR[array_desc->iad_total_length]);
10061007
blob->BLB_get_data(tdbb, data, array_desc->iad_total_length);
10071008
const USHORT dimensions = array_desc->iad_dimensions;
10081009

@@ -1012,39 +1013,29 @@ static SLONG get_scalar_array(const Parameter* arg,
10121013
dsc from = array_desc->iad_rpt[0].iad_desc;
10131014

10141015
if (to.dsc_dtype != from.dsc_dtype ||
1015-
to.dsc_scale != from.dsc_scale || to.dsc_length != from.dsc_length)
1016+
to.dsc_scale != from.dsc_scale ||
1017+
to.dsc_length != from.dsc_length)
10161018
{
1017-
SLONG n = array_desc->iad_count;
1018-
UCHAR* const temp = FB_NEW_POOL(*getDefaultMemoryPool()) UCHAR[static_cast<size_t>(to.dsc_length * n)];
1019+
ULONG n = array_desc->iad_count;
1020+
AutoPtr<UCHAR, ArrayDelete> temp(FB_NEW_POOL(pool) UCHAR[to.dsc_length * n]);
10191021
to.dsc_address = temp;
10201022
from.dsc_address = data;
10211023

1022-
// This loop may call ERR_post indirectly.
1023-
try
1024-
{
1025-
for (; n; --n, to.dsc_address += to.dsc_length,
1026-
from.dsc_address += array_desc->iad_element_length)
1027-
{
1028-
MOV_move(tdbb, &from, &to);
1029-
}
1030-
}
1031-
catch (const Exception&)
1024+
for (; n; --n, to.dsc_address += to.dsc_length,
1025+
from.dsc_address += array_desc->iad_element_length)
10321026
{
1033-
delete[] data;
1034-
delete[] temp;
1035-
throw;
1027+
MOV_move(tdbb, &from, &to);
10361028
}
10371029

1038-
delete[] data;
1039-
data = temp;
1030+
data = temp.release();
10401031
}
10411032

10421033
// Fill out the scalar array descriptor
10431034

1044-
stack.push(data);
10451035
scalar_desc->sad_desc = arg->prm_desc;
10461036
scalar_desc->sad_desc.dsc_address = data;
10471037
scalar_desc->sad_dimensions = dimensions;
1038+
stack.push(data.release());
10481039

10491040
const Ods::InternalArrayDesc::iad_repeat* tail1 = array_desc->iad_rpt;
10501041
scalar_array_desc::sad_repeat* tail2 = scalar_desc->sad_rpt;
@@ -1055,7 +1046,8 @@ static SLONG get_scalar_array(const Parameter* arg,
10551046
tail2->sad_lower = tail1->iad_lower;
10561047
}
10571048

1058-
return static_cast<SLONG>(sizeof(scalar_array_desc) + (dimensions - 1u) * sizeof(scalar_array_desc::sad_repeat));
1049+
return static_cast<ULONG>(sizeof(scalar_array_desc) +
1050+
(dimensions - 1u) * sizeof(scalar_array_desc::sad_repeat));
10591051
}
10601052

10611053

0 commit comments

Comments
 (0)