Skip to content

Commit 55c7cea

Browse files
committed
ICU-23128 Don't clobber UErrorCode on expected U_BUFFER_OVERFLOW_ERROR.
When it's expected that a function call might result in setting U_BUFFER_OVERFLOW_ERROR upon which a new buffer is allocated and the function call is retried, this should upon success not overwrite any already set value of UErrorCode, as this could accidentally overwrite some valid and meaningful value when this was other than U_ZERO_ERROR.
1 parent a965353 commit 55c7cea

File tree

14 files changed

+183
-131
lines changed

14 files changed

+183
-131
lines changed

icu4c/source/common/locid.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,14 +2674,15 @@ Locale::setKeywordValue(StringPiece keywordName,
26742674
// Remove -1 from the capacity so that this function can guarantee NUL termination.
26752675
CheckedArrayByteSink sink(fullName + offset, capacity - offset - 1);
26762676

2677+
UErrorCode bufferStatus = U_ZERO_ERROR;
26772678
int32_t reslen = ulocimp_setKeywordValue(
26782679
{fullName + offset, static_cast<std::string_view::size_type>(length - offset)},
26792680
keywordName,
26802681
keywordValue,
26812682
sink,
2682-
status);
2683+
bufferStatus);
26832684

2684-
if (status == U_BUFFER_OVERFLOW_ERROR) {
2685+
if (bufferStatus == U_BUFFER_OVERFLOW_ERROR) {
26852686
capacity = reslen + offset + 1;
26862687
char* newFullName = static_cast<char*>(uprv_malloc(capacity));
26872688
if (newFullName == nullptr) {
@@ -2697,11 +2698,13 @@ Locale::setKeywordValue(StringPiece keywordName,
26972698
uprv_free(fullName);
26982699
}
26992700
fullName = newFullName;
2700-
status = U_ZERO_ERROR;
27012701
continue;
27022702
}
27032703

2704-
if (U_FAILURE(status)) { return; }
2704+
if (U_FAILURE(bufferStatus)) {
2705+
status = bufferStatus;
2706+
return;
2707+
}
27052708
u_terminateChars(fullName, capacity, reslen + offset, &status);
27062709
break;
27072710
}

icu4c/source/common/rbbisetb.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,10 @@ int32_t RBBISetBuilder::getTrieSize() {
328328
UCPTRIE_TYPE_FAST,
329329
use8Bits ? UCPTRIE_VALUE_BITS_8 : UCPTRIE_VALUE_BITS_16,
330330
fStatus);
331-
fTrieSize = ucptrie_toBinary(fTrie, nullptr, 0, fStatus);
332-
if (*fStatus == U_BUFFER_OVERFLOW_ERROR) {
333-
*fStatus = U_ZERO_ERROR;
331+
UErrorCode bufferStatus = *fStatus;
332+
fTrieSize = ucptrie_toBinary(fTrie, nullptr, 0, &bufferStatus);
333+
if (bufferStatus != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(bufferStatus)) {
334+
*fStatus = bufferStatus;
334335
}
335336
}
336337
return fTrieSize;

icu4c/source/common/ucasemap.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ ucasemap_setLocale(UCaseMap *csm, const char *locale, UErrorCode *pErrorCode) {
102102
return;
103103
}
104104

105-
int32_t length=uloc_getName(locale, csm->locale, (int32_t)sizeof(csm->locale), pErrorCode);
106-
if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR || length==sizeof(csm->locale)) {
107-
*pErrorCode=U_ZERO_ERROR;
105+
UErrorCode bufferStatus = U_ZERO_ERROR;
106+
int32_t length=uloc_getName(locale, csm->locale, (int32_t)sizeof(csm->locale), &bufferStatus);
107+
if(bufferStatus==U_BUFFER_OVERFLOW_ERROR || length==sizeof(csm->locale)) {
108108
/* we only really need the language code for case mappings */
109109
length=uloc_getLanguage(locale, csm->locale, (int32_t)sizeof(csm->locale), pErrorCode);
110110
}

icu4c/source/common/ucnv.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,20 +1752,24 @@ ucnv_fromUChars(UConverter *cnv,
17521752
destLimit=dest+destCapacity;
17531753

17541754
/* perform the conversion */
1755-
ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, pErrorCode);
1755+
UErrorCode bufferStatus = U_ZERO_ERROR;
1756+
ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, &bufferStatus);
17561757
destLength=(int32_t)(dest-originalDest);
17571758

17581759
/* if an overflow occurs, then get the preflighting length */
1759-
if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
1760+
if(bufferStatus==U_BUFFER_OVERFLOW_ERROR) {
17601761
char buffer[1024];
17611762

17621763
destLimit=buffer+sizeof(buffer);
17631764
do {
17641765
dest=buffer;
1765-
*pErrorCode=U_ZERO_ERROR;
1766-
ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, pErrorCode);
1766+
bufferStatus=U_ZERO_ERROR;
1767+
ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, &bufferStatus);
17671768
destLength+=(int32_t)(dest-buffer);
1768-
} while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
1769+
} while(bufferStatus==U_BUFFER_OVERFLOW_ERROR);
1770+
}
1771+
if (U_FAILURE(bufferStatus)) {
1772+
*pErrorCode = bufferStatus;
17691773
}
17701774
} else {
17711775
destLength=0;
@@ -1808,22 +1812,26 @@ ucnv_toUChars(UConverter *cnv,
18081812
destLimit=dest+destCapacity;
18091813

18101814
/* perform the conversion */
1811-
ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, pErrorCode);
1815+
UErrorCode bufferStatus = U_ZERO_ERROR;
1816+
ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, &bufferStatus);
18121817
destLength=(int32_t)(dest-originalDest);
18131818

18141819
/* if an overflow occurs, then get the preflighting length */
1815-
if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR)
1820+
if(bufferStatus==U_BUFFER_OVERFLOW_ERROR)
18161821
{
18171822
char16_t buffer[1024];
18181823

18191824
destLimit=buffer+UPRV_LENGTHOF(buffer);
18201825
do {
18211826
dest=buffer;
1822-
*pErrorCode=U_ZERO_ERROR;
1823-
ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, pErrorCode);
1827+
bufferStatus=U_ZERO_ERROR;
1828+
ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, nullptr, true, &bufferStatus);
18241829
destLength+=(int32_t)(dest-buffer);
18251830
}
1826-
while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
1831+
while(bufferStatus==U_BUFFER_OVERFLOW_ERROR);
1832+
}
1833+
if (U_FAILURE(bufferStatus)) {
1834+
*pErrorCode = bufferStatus;
18271835
}
18281836
} else {
18291837
destLength=0;

icu4c/source/common/uidna.cpp

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,10 @@ _internal_toASCII(const char16_t* src, int32_t srcLength,
248248
if(srcIsASCII == false){
249249

250250
// step 2
251-
b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Capacity, namePrepOptions, parseError, status);
251+
UErrorCode bufferStatus = U_ZERO_ERROR;
252+
b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Capacity, namePrepOptions, parseError, &bufferStatus);
252253

253-
if(*status == U_BUFFER_OVERFLOW_ERROR){
254+
if(bufferStatus == U_BUFFER_OVERFLOW_ERROR){
254255
// redo processing of string
255256
// we do not have enough room so grow the buffer
256257
if(b1 != b1Stack){
@@ -262,9 +263,12 @@ _internal_toASCII(const char16_t* src, int32_t srcLength,
262263
goto CLEANUP;
263264
}
264265

265-
*status = U_ZERO_ERROR; // reset error
266-
267-
b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Len, namePrepOptions, parseError, status);
266+
bufferStatus = U_ZERO_ERROR; // reset error
267+
268+
b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Len, namePrepOptions, parseError, &bufferStatus);
269+
}
270+
if (U_FAILURE(bufferStatus)) {
271+
*status = bufferStatus;
268272
}
269273
}
270274
// error bail out
@@ -333,9 +337,10 @@ _internal_toASCII(const char16_t* src, int32_t srcLength,
333337
// caseFlags = (UBool*) uprv_malloc(b1Len * sizeof(UBool));
334338
// uprv_memset(caseFlags,true,b1Len);
335339

336-
b2Len = u_strToPunycode(b1,b1Len,b2,b2Capacity,caseFlags, status);
340+
UErrorCode bufferStatus = U_ZERO_ERROR;
341+
b2Len = u_strToPunycode(b1,b1Len,b2,b2Capacity,caseFlags,&bufferStatus);
337342

338-
if(*status == U_BUFFER_OVERFLOW_ERROR){
343+
if(bufferStatus == U_BUFFER_OVERFLOW_ERROR){
339344
// redo processing of string
340345
/* we do not have enough room so grow the buffer*/
341346
b2 = static_cast<char16_t*>(uprv_malloc(b2Len * U_SIZEOF_UCHAR));
@@ -344,12 +349,13 @@ _internal_toASCII(const char16_t* src, int32_t srcLength,
344349
goto CLEANUP;
345350
}
346351

347-
*status = U_ZERO_ERROR; // reset error
348-
349-
b2Len = u_strToPunycode(b1,b1Len,b2,b2Len,caseFlags, status);
352+
bufferStatus = U_ZERO_ERROR; // reset error
353+
354+
b2Len = u_strToPunycode(b1,b1Len,b2,b2Len,caseFlags,&bufferStatus);
350355
}
351356
//error bail out
352-
if(U_FAILURE(*status)){
357+
if(U_FAILURE(bufferStatus)){
358+
*status = bufferStatus;
353359
goto CLEANUP;
354360
}
355361
// TODO : Reconsider while implementing the case preserve RFE
@@ -454,8 +460,9 @@ _internal_toUnicode(const char16_t* src, int32_t srcLength,
454460

455461
if(srcIsASCII == false){
456462
// step 2: process the string
457-
b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Capacity, namePrepOptions, parseError, status);
458-
if(*status == U_BUFFER_OVERFLOW_ERROR){
463+
UErrorCode bufferStatus = U_ZERO_ERROR;
464+
b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Capacity, namePrepOptions, parseError, &bufferStatus);
465+
if(bufferStatus == U_BUFFER_OVERFLOW_ERROR){
459466
// redo processing of string
460467
/* we do not have enough room so grow the buffer*/
461468
b1 = static_cast<char16_t*>(uprv_malloc(b1Len * U_SIZEOF_UCHAR));
@@ -464,12 +471,13 @@ _internal_toUnicode(const char16_t* src, int32_t srcLength,
464471
goto CLEANUP;
465472
}
466473

467-
*status = U_ZERO_ERROR; // reset error
468-
469-
b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Len, namePrepOptions, parseError, status);
474+
bufferStatus = U_ZERO_ERROR; // reset error
475+
476+
b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Len, namePrepOptions, parseError, &bufferStatus);
470477
}
471478
//bail out on error
472-
if(U_FAILURE(*status)){
479+
if(U_FAILURE(bufferStatus)){
480+
*status = bufferStatus;
473481
goto CLEANUP;
474482
}
475483
}else{
@@ -493,9 +501,10 @@ _internal_toUnicode(const char16_t* src, int32_t srcLength,
493501
b1PrimeLen = b1Len - ACE_PREFIX_LENGTH;
494502

495503
//step 5: Decode using punycode
496-
b2Len = u_strFromPunycode(b1Prime, b1PrimeLen, b2, b2Capacity, caseFlags,status);
504+
UErrorCode bufferStatus = U_ZERO_ERROR;
505+
b2Len = u_strFromPunycode(b1Prime, b1PrimeLen, b2, b2Capacity, caseFlags, &bufferStatus);
497506

498-
if(*status == U_BUFFER_OVERFLOW_ERROR){
507+
if(bufferStatus == U_BUFFER_OVERFLOW_ERROR){
499508
// redo processing of string
500509
/* we do not have enough room so grow the buffer*/
501510
b2 = static_cast<char16_t*>(uprv_malloc(b2Len * U_SIZEOF_UCHAR));
@@ -504,16 +513,16 @@ _internal_toUnicode(const char16_t* src, int32_t srcLength,
504513
goto CLEANUP;
505514
}
506515

507-
*status = U_ZERO_ERROR; // reset error
516+
bufferStatus = U_ZERO_ERROR; // reset error
508517

509-
b2Len = u_strFromPunycode(b1Prime, b1PrimeLen, b2, b2Len, caseFlags, status);
518+
b2Len = u_strFromPunycode(b1Prime, b1PrimeLen, b2, b2Len, caseFlags, &bufferStatus);
510519
}
511520

512521

513522
//step 6:Apply toASCII
514-
b3Len = uidna_toASCII(b2, b2Len, b3, b3Capacity, options, parseError, status);
523+
b3Len = uidna_toASCII(b2, b2Len, b3, b3Capacity, options, parseError, &bufferStatus);
515524

516-
if(*status == U_BUFFER_OVERFLOW_ERROR){
525+
if(bufferStatus == U_BUFFER_OVERFLOW_ERROR){
517526
// redo processing of string
518527
/* we do not have enough room so grow the buffer*/
519528
b3 = static_cast<char16_t*>(uprv_malloc(b3Len * U_SIZEOF_UCHAR));
@@ -522,13 +531,14 @@ _internal_toUnicode(const char16_t* src, int32_t srcLength,
522531
goto CLEANUP;
523532
}
524533

525-
*status = U_ZERO_ERROR; // reset error
534+
bufferStatus = U_ZERO_ERROR; // reset error
526535

527-
b3Len = uidna_toASCII(b2,b2Len,b3,b3Len,options,parseError, status);
536+
b3Len = uidna_toASCII(b2,b2Len,b3,b3Len,options,parseError,&bufferStatus);
528537

529538
}
530539
//bail out on error
531-
if(U_FAILURE(*status)){
540+
if(U_FAILURE(bufferStatus)){
541+
*status = bufferStatus;
532542
goto CLEANUP;
533543
}
534544

@@ -706,24 +716,21 @@ uidna_IDNToASCII( const char16_t *src, int32_t srcLength,
706716
labelLen = getNextSeparator(labelStart,remainingLen, &delimiter,&done);
707717
labelReqLength = 0;
708718
if(!(labelLen==0 && done)){// make sure this is not a root label separator.
709-
710-
labelReqLength = _internal_toASCII( labelStart, labelLen,
711-
currentDest, remainingDestCapacity,
712-
options, nameprep,
713-
parseError, status);
714-
715-
if(*status == U_BUFFER_OVERFLOW_ERROR){
716-
717-
*status = U_ZERO_ERROR; // reset error
719+
720+
UErrorCode bufferStatus = U_ZERO_ERROR;
721+
labelReqLength = _internal_toASCII( labelStart, labelLen,
722+
currentDest, remainingDestCapacity,
723+
options, nameprep,
724+
parseError, &bufferStatus);
725+
726+
if (bufferStatus == U_BUFFER_OVERFLOW_ERROR) {
718727
remainingDestCapacity = 0;
728+
} else if (U_FAILURE(bufferStatus)) {
729+
*status = bufferStatus;
730+
break;
719731
}
720732
}
721733

722-
723-
if(U_FAILURE(*status)){
724-
break;
725-
}
726-
727734
reqLength +=labelReqLength;
728735
// adjust the destination pointer
729736
if(labelReqLength < remainingDestCapacity){
@@ -877,35 +884,39 @@ uidna_compare( const char16_t *s1, int32_t length1,
877884

878885
UParseError parseError;
879886

880-
b1Len = uidna_IDNToASCII(s1, length1, b1, b1Capacity, options, &parseError, status);
881-
if(*status == U_BUFFER_OVERFLOW_ERROR){
887+
UErrorCode bufferStatus = U_ZERO_ERROR;
888+
b1Len = uidna_IDNToASCII(s1, length1, b1, b1Capacity, options, &parseError, &bufferStatus);
889+
if(bufferStatus == U_BUFFER_OVERFLOW_ERROR){
882890
// redo processing of string
883891
b1 = (char16_t*) uprv_malloc(b1Len * U_SIZEOF_UCHAR);
884892
if(b1==nullptr){
885893
*status = U_MEMORY_ALLOCATION_ERROR;
886894
goto CLEANUP;
887895
}
888896

889-
*status = U_ZERO_ERROR; // reset error
890-
891-
b1Len = uidna_IDNToASCII(s1,length1,b1,b1Len, options, &parseError, status);
892-
897+
bufferStatus = U_ZERO_ERROR; // reset error
898+
899+
b1Len = uidna_IDNToASCII(s1,length1,b1,b1Len, options, &parseError, &bufferStatus);
893900
}
894901

895-
b2Len = uidna_IDNToASCII(s2,length2, b2,b2Capacity, options, &parseError, status);
896-
if(*status == U_BUFFER_OVERFLOW_ERROR){
902+
b2Len = uidna_IDNToASCII(s2,length2, b2,b2Capacity, options, &parseError, &bufferStatus);
903+
if(bufferStatus == U_BUFFER_OVERFLOW_ERROR){
897904
// redo processing of string
898905
b2 = (char16_t*) uprv_malloc(b2Len * U_SIZEOF_UCHAR);
899906
if(b2==nullptr){
900907
*status = U_MEMORY_ALLOCATION_ERROR;
901908
goto CLEANUP;
902909
}
903910

904-
*status = U_ZERO_ERROR; // reset error
905-
906-
b2Len = uidna_IDNToASCII(s2, length2, b2, b2Len, options, &parseError, status);
907-
911+
bufferStatus = U_ZERO_ERROR; // reset error
912+
913+
b2Len = uidna_IDNToASCII(s2, length2, b2, b2Len, options, &parseError, &bufferStatus);
914+
}
915+
916+
if (U_FAILURE(bufferStatus)) {
917+
*status = bufferStatus;
908918
}
919+
909920
// when toASCII is applied all label separators are replaced with FULL_STOP
910921
result = compareCaseInsensitiveASCII(b1,b1Len,b2,b2Len);
911922

0 commit comments

Comments
 (0)