From d9e954dc93f0a3a4bde5bd1af88583795200ffff Mon Sep 17 00:00:00 2001 From: Markus Scherer Date: Sun, 6 Aug 2006 22:38:31 +0000 Subject: [PATCH] ICU-5220 uenum_next() must not set an error code for just enumerating past the end X-SVN-Rev: 19989 --- icu4c/source/common/ucnv_io.c | 8 ++++++-- icu4c/source/common/uenumimp.h | 16 +++++++++------- icu4c/source/i18n/csdetect.cpp | 8 ++++++-- icu4c/source/i18n/ucurr.cpp | 4 +++- icu4c/source/test/cintltst/ccapitst.c | 5 ++++- icu4c/source/test/cintltst/currtest.c | 7 +++++-- icu4c/source/test/cintltst/stdnmtst.c | 13 +++++++++---- icu4c/source/test/cintltst/ucsdetst.c | 11 ++++++++--- 8 files changed, 50 insertions(+), 22 deletions(-) diff --git a/icu4c/source/common/ucnv_io.c b/icu4c/source/common/ucnv_io.c index e1e6e0214b6..4e570e55d9c 100644 --- a/icu4c/source/common/ucnv_io.c +++ b/icu4c/source/common/ucnv_io.c @@ -790,7 +790,9 @@ ucnv_io_nextStandardAliases(UEnumeration *enumerator, } } /* Either we accessed a zero length list, or we enumerated too far. */ - *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR; + if (resultLength) { + *resultLength = 0; + } return NULL; } @@ -1021,7 +1023,9 @@ ucnv_io_nextAllConverters(UEnumeration *enumerator, return myStr; } /* Either we accessed a zero length list, or we enumerated too far. */ - *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR; + if (resultLength) { + *resultLength = 0; + } return NULL; } diff --git a/icu4c/source/common/uenumimp.h b/icu4c/source/common/uenumimp.h index 2c5cc3acaf3..664bc686644 100644 --- a/icu4c/source/common/uenumimp.h +++ b/icu4c/source/common/uenumimp.h @@ -1,7 +1,7 @@ /* ******************************************************************************* * -* Copyright (C) 2002, International Business Machines +* Copyright (C) 2002-2006, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* @@ -58,13 +58,14 @@ UEnumCount(UEnumeration *en, UErrorCode *status); /** * Function type declaration for uenum_unext(). * - * This function should return the next element - * as a UChar * + * This function returns the next element as a UChar *, + * or NULL after all elements haven been enumerated. * * @param en enumeration * @param resultLength pointer to result length * @param status pointer to UErrorCode variable - * @return next element as UChar * + * @return next element as UChar *, + * or NULL after all elements haven been enumerated */ typedef const UChar* U_CALLCONV UEnumUNext(UEnumeration* en, @@ -74,13 +75,14 @@ UEnumUNext(UEnumeration* en, /** * Function type declaration for uenum_next(). * - * This function should return the next element - * as a char * + * This function returns the next element as a char *, + * or NULL after all elements haven been enumerated. * * @param en enumeration * @param resultLength pointer to result length * @param status pointer to UErrorCode variable - * @return next element as char * + * @return next element as char *, + * or NULL after all elements haven been enumerated */ typedef const char* U_CALLCONV UEnumNext(UEnumeration* en, diff --git a/icu4c/source/i18n/csdetect.cpp b/icu4c/source/i18n/csdetect.cpp index 1df7eb37a81..43ac7b736d7 100644 --- a/icu4c/source/i18n/csdetect.cpp +++ b/icu4c/source/i18n/csdetect.cpp @@ -303,11 +303,15 @@ enumCount(UEnumeration *, UErrorCode *) { static const char* U_CALLCONV enumNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { if(((Context *)en->context)->currIndex >= fCSRecognizers_size) { - *status = U_INDEX_OUTOFBOUNDS_ERROR; + if(resultLength != NULL) { + *resultLength = 0; + } return NULL; } const char *currName = fCSRecognizers[((Context *)en->context)->currIndex]->getName(); - *resultLength = (int32_t)uprv_strlen(currName); + if(resultLength != NULL) { + *resultLength = (int32_t)uprv_strlen(currName); + } ((Context *)en->context)->currIndex++; return currName; diff --git a/icu4c/source/i18n/ucurr.cpp b/icu4c/source/i18n/ucurr.cpp index 5cb2eecfd7d..5b0eed9da97 100644 --- a/icu4c/source/i18n/ucurr.cpp +++ b/icu4c/source/i18n/ucurr.cpp @@ -1044,7 +1044,9 @@ ucurr_nextCurrencyList(UEnumeration *enumerator, } } /* We enumerated too far. */ - *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR; + if (resultLength) { + *resultLength = 0; + } return NULL; } diff --git a/icu4c/source/test/cintltst/ccapitst.c b/icu4c/source/test/cintltst/ccapitst.c index 80573f6965d..daa73bd5aeb 100644 --- a/icu4c/source/test/cintltst/ccapitst.c +++ b/icu4c/source/test/cintltst/ccapitst.c @@ -169,7 +169,10 @@ static void ListNames(void) { count1++; log_verbose("read \"%s\", length %i\n", string, len); } - err = U_ZERO_ERROR; + if (U_FAILURE(err)) { + log_err("FAILURE! uenum_next(allNamesEnum...) set an error: %s\n", u_errorName(err)); + err = U_ZERO_ERROR; + } uenum_reset(allNamesEnum, &err); while ((string = uenum_next(allNamesEnum, &len, &err))) { count2++; diff --git a/icu4c/source/test/cintltst/currtest.c b/icu4c/source/test/cintltst/currtest.c index dd67ca2aa0d..93bbee0afa1 100644 --- a/icu4c/source/test/cintltst/currtest.c +++ b/icu4c/source/test/cintltst/currtest.c @@ -1,6 +1,6 @@ /******************************************************************** * COPYRIGHT: - * Copyright (c) 2005-2005, International Business Machines Corporation and + * Copyright (c) 2005-2006, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ #include "unicode/utypes.h" @@ -119,7 +119,7 @@ static int32_t checkItemCount(uint32_t currencyType) { originalCount = uenum_count(en, &status); for (count=0;;count++) { const char *str = uenum_next(en, &len, &status); - if (U_FAILURE(status) || len != expectedLen || strlen(str) != expectedLen) { + if (str == NULL || len != expectedLen || strlen(str) != expectedLen) { break; } } @@ -128,6 +128,9 @@ static int32_t checkItemCount(uint32_t currencyType) { log_err("Error: uenum_count returned the wrong value (type = 0x%X). Got: %d Expected %d\n", currencyType, count, originalCount); } + if (U_FAILURE(status)) { + log_err("Error: uenum_next got an error: %s\n", u_errorName(status)); + } uenum_close(en); return count; } diff --git a/icu4c/source/test/cintltst/stdnmtst.c b/icu4c/source/test/cintltst/stdnmtst.c index 1b71f7cf8aa..676ac869cba 100644 --- a/icu4c/source/test/cintltst/stdnmtst.c +++ b/icu4c/source/test/cintltst/stdnmtst.c @@ -170,8 +170,9 @@ static void TestCanonicalName() static UBool doTestNames(const char *name, const char *standard, const char **expected, int32_t size) { UErrorCode err = U_ZERO_ERROR; UEnumeration *myEnum = ucnv_openStandardNames(name, standard, &err); + const char *enumName, *testName; int32_t enumCount = uenum_count(myEnum, &err); - int32_t idx, repeatTimes = 3; + int32_t idx, len, repeatTimes = 3; if (size != enumCount) { log_err("FAIL: different size arrays. Got %d. Expected %d\n", enumCount, size); return 0; @@ -183,9 +184,8 @@ static UBool doTestNames(const char *name, const char *standard, const char **ex log_verbose("\n%s %s\n", name, standard); while (repeatTimes-- > 0) { for (idx = 0; idx < enumCount; idx++) { - int32_t len; - const char *enumName = uenum_next(myEnum, &len, &err); - const char *testName = expected[idx]; + enumName = uenum_next(myEnum, &len, &err); + testName = expected[idx]; if (uprv_strcmp(enumName, testName) != 0 || U_FAILURE(err) || len != (int32_t)uprv_strlen(expected[idx])) { @@ -195,6 +195,11 @@ static UBool doTestNames(const char *name, const char *standard, const char **ex log_verbose("%s\n", enumName); err = U_ZERO_ERROR; } + /* one past the list of all names must return NULL */ + enumName = uenum_next(myEnum, &len, &err); + if (enumName != NULL || len != 0 || U_FAILURE(err)) { + log_err("FAIL: uenum_next(past the list) did not return NULL[0] with U_SUCCESS()\n"); + } log_verbose("\n reset\n"); uenum_reset(myEnum, &err); if (U_FAILURE(err)) { diff --git a/icu4c/source/test/cintltst/ucsdetst.c b/icu4c/source/test/cintltst/ucsdetst.c index ebc13c310c6..3c884e474f9 100644 --- a/icu4c/source/test/cintltst/ucsdetst.c +++ b/icu4c/source/test/cintltst/ucsdetst.c @@ -95,17 +95,22 @@ static void TestConstruction(void) UErrorCode status = U_ZERO_ERROR; UCharsetDetector *csd = ucsdet_open(&status); UEnumeration *e = ucsdet_getAllDetectableCharsets(csd, &status); + const char *name; int32_t count = uenum_count(e, &status); - int32_t i; + int32_t i, length; for(i = 0; i < count; i += 1) { - int32_t length; - const char *name = uenum_next(e, &length, &status); + name = uenum_next(e, &length, &status); if(name == NULL || length <= 0) { log_err("ucsdet_getAllDetectableCharsets() returned a null or empty name!\n"); } } + /* one past the list of all names must return NULL */ + name = uenum_next(e, &length, &status); + if(name != NULL || length != 0 || U_FAILURE(status)) { + log_err("ucsdet_getAllDetectableCharsets(past the list) returned a non-null name!\n"); + } uenum_close(e); ucsdet_close(csd);