Skip to content

Commit

Permalink
Fix #5534 - String truncation exception on UPPER/LOWER functions, UTF…
Browse files Browse the repository at this point in the history
…8 database and some multibyte characters.
  • Loading branch information
asfernandes committed Jun 11, 2021
1 parent 8e6d4b2 commit 378b0fe
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/common/IntlUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ ULONG IntlUtil::toLower(Jrd::CharSet* cs, ULONG srcLen, const UCHAR* src, ULONG
Firebird::HalfStaticArray<UCHAR, BUFFER_SMALL> utf16_str;
UCHAR* utf16_ptr;

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

if (dstLen >= utf16_length) // if dst buffer is sufficient large, use it as intermediate
if (dst != src && dstLen >= utf16_length) // if dst buffer is sufficient large, use it as intermediate
utf16_ptr = dst;
else
utf16_ptr = utf16_str.getBuffer(utf16_length);
Expand Down
19 changes: 11 additions & 8 deletions src/dsql/ExprNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10675,6 +10675,7 @@ dsc* StrCaseNode::execute(thread_db* tdbb, jrd_req* request) const
return NULL;

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

if (value->isBlob())
Expand All @@ -10689,21 +10690,23 @@ dsc* StrCaseNode::execute(thread_db* tdbb, jrd_req* request) const
blb* blob = blb::open(tdbb, tdbb->getRequest()->req_transaction,
reinterpret_cast<bid*>(value->dsc_address));

HalfStaticArray<UCHAR, BUFFER_SMALL> buffer;
HalfStaticArray<UCHAR, BUFFER_MEDIUM> buffer;

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

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

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

if (len)
{
len = (textType->*intlFunction)(len, buffer.begin(), len, buffer.begin());
len = (textType->*intlFunction)(len, buffer.begin(), buffer.getCapacity(), buffer.begin());
newBlob->BLB_put_data(tdbb, buffer.begin(), len);
}
}
Expand All @@ -10716,16 +10719,16 @@ dsc* StrCaseNode::execute(thread_db* tdbb, jrd_req* request) const
UCHAR* ptr;
VaryStr<TEMP_STR_LENGTH> temp;
USHORT ttype;
ULONG len = MOV_get_string_ptr(tdbb, value, &ttype, &ptr, &temp, sizeof(temp));

dsc desc;
desc.dsc_length = MOV_get_string_ptr(tdbb, value, &ttype, &ptr, &temp, sizeof(temp));
desc.dsc_length = len / charSet->minBytesPerChar() * charSet->maxBytesPerChar();
desc.dsc_dtype = dtype_text;
desc.dsc_address = NULL;
desc.setTextType(ttype);
EVL_make_value(tdbb, &desc, impure);

ULONG len = (textType->*intlFunction)(desc.dsc_length,
ptr, desc.dsc_length, impure->vlu_desc.dsc_address);
len = (textType->*intlFunction)(len, ptr, desc.dsc_length, impure->vlu_desc.dsc_address);

if (len == INTL_BAD_STR_LENGTH)
status_exception::raise(Arg::Gds(isc_arith_except));
Expand Down

0 comments on commit 378b0fe

Please sign in to comment.