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:
parent
8e6d4b271f
commit
378b0fe15e
@ -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);
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user