Skip to content

Commit 395b498

Browse files
committed
Fix #5534 - String truncation exception on UPPER/LOWER functions, UTF8 database and some multibyte characters.
1 parent cd0682b commit 395b498

File tree

2 files changed

+13
-10
lines changed

2 files changed

+13
-10
lines changed

src/common/IntlUtil.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ ULONG IntlUtil::toLower(Jrd::CharSet* cs, ULONG srcLen, const UCHAR* src, ULONG
601601
Firebird::HalfStaticArray<UCHAR, BUFFER_SMALL> utf16_str;
602602
UCHAR* utf16_ptr;
603603

604-
if (dstLen >= utf16_length) // if dst buffer is sufficient large, use it as intermediate
604+
if (dst != src && dstLen >= utf16_length) // if dst buffer is sufficient large, use it as intermediate
605605
utf16_ptr = dst;
606606
else
607607
utf16_ptr = utf16_str.getBuffer(utf16_length);
@@ -627,7 +627,7 @@ ULONG IntlUtil::toUpper(Jrd::CharSet* cs, ULONG srcLen, const UCHAR* src, ULONG
627627
Firebird::HalfStaticArray<UCHAR, BUFFER_SMALL> utf16_str;
628628
UCHAR* utf16_ptr;
629629

630-
if (dstLen >= utf16_length) // if dst buffer is sufficient large, use it as intermediate
630+
if (dst != src && dstLen >= utf16_length) // if dst buffer is sufficient large, use it as intermediate
631631
utf16_ptr = dst;
632632
else
633633
utf16_ptr = utf16_str.getBuffer(utf16_length);

src/dsql/ExprNodes.cpp

+11-8
Original file line numberDiff line numberDiff line change
@@ -10702,6 +10702,7 @@ dsc* StrCaseNode::execute(thread_db* tdbb, jrd_req* request) const
1070210702
return NULL;
1070310703

1070410704
TextType* textType = INTL_texttype_lookup(tdbb, value->getTextType());
10705+
CharSet* charSet = textType->getCharSet();
1070510706
auto intlFunction = (blrOp == blr_lowcase ? &TextType::str_to_lower : &TextType::str_to_upper);
1070610707

1070710708
if (value->isBlob())
@@ -10716,21 +10717,23 @@ dsc* StrCaseNode::execute(thread_db* tdbb, jrd_req* request) const
1071610717
blb* blob = blb::open(tdbb, tdbb->getRequest()->req_transaction,
1071710718
reinterpret_cast<bid*>(value->dsc_address));
1071810719

10719-
HalfStaticArray<UCHAR, BUFFER_SMALL> buffer;
10720+
HalfStaticArray<UCHAR, BUFFER_MEDIUM> buffer;
1072010721

1072110722
if (charSet->isMultiByte())
10722-
buffer.getBuffer(blob->blb_length); // alloc space to put entire blob in memory
10723+
{
10724+
// Alloc space to put entire blob in memory, with extra space for additional bytes when changing case.
10725+
buffer.getBuffer(blob->blb_length / charSet->minBytesPerChar() * charSet->maxBytesPerChar());
10726+
}
1072310727

10724-
blb* newBlob = blb::create(tdbb, tdbb->getRequest()->req_transaction,
10725-
&impure->vlu_misc.vlu_bid);
10728+
blb* newBlob = blb::create(tdbb, tdbb->getRequest()->req_transaction, &impure->vlu_misc.vlu_bid);
1072610729

1072710730
while (!(blob->blb_flags & BLB_eof))
1072810731
{
1072910732
SLONG len = blob->BLB_get_data(tdbb, buffer.begin(), buffer.getCapacity(), false);
1073010733

1073110734
if (len)
1073210735
{
10733-
len = (textType->*intlFunction)(len, buffer.begin(), len, buffer.begin());
10736+
len = (textType->*intlFunction)(len, buffer.begin(), buffer.getCapacity(), buffer.begin());
1073410737
newBlob->BLB_put_data(tdbb, buffer.begin(), len);
1073510738
}
1073610739
}
@@ -10743,16 +10746,16 @@ dsc* StrCaseNode::execute(thread_db* tdbb, jrd_req* request) const
1074310746
UCHAR* ptr;
1074410747
VaryStr<TEMP_STR_LENGTH> temp;
1074510748
USHORT ttype;
10749+
ULONG len = MOV_get_string_ptr(tdbb, value, &ttype, &ptr, &temp, sizeof(temp));
1074610750

1074710751
dsc desc;
10748-
desc.dsc_length = MOV_get_string_ptr(tdbb, value, &ttype, &ptr, &temp, sizeof(temp));
10752+
desc.dsc_length = len / charSet->minBytesPerChar() * charSet->maxBytesPerChar();
1074910753
desc.dsc_dtype = dtype_text;
1075010754
desc.dsc_address = NULL;
1075110755
desc.setTextType(ttype);
1075210756
EVL_make_value(tdbb, &desc, impure);
1075310757

10754-
ULONG len = (textType->*intlFunction)(desc.dsc_length,
10755-
ptr, desc.dsc_length, impure->vlu_desc.dsc_address);
10758+
len = (textType->*intlFunction)(len, ptr, desc.dsc_length, impure->vlu_desc.dsc_address);
1075610759

1075710760
if (len == INTL_BAD_STR_LENGTH)
1075810761
status_exception::raise(Arg::Gds(isc_arith_except));

0 commit comments

Comments
 (0)