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

Fix #5534 - String truncation exception on UPPER/LOWER functions, UTF8 database and some multibyte characters.

This commit is contained in:
Adriano dos Santos Fernandes 2021-06-11 09:45:22 -03:00
parent 8e6d4b271f
commit 378b0fe15e
2 changed files with 13 additions and 10 deletions

View File

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

View File

@ -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())
@ -10689,13 +10690,15 @@ 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))
{
@ -10703,7 +10706,7 @@ dsc* StrCaseNode::execute(thread_db* tdbb, jrd_req* request) const
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);
}
}
@ -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));