blob: 34fe515a49f1b449f788adb397b7507cf02a0555 [file] [log] [blame]
diff --git a/source/common/locid.cpp b/source/common/locid.cpp
index 1efe0da9..feadbcbc 100644
--- a/source/common/locid.cpp
+++ b/source/common/locid.cpp
@@ -2457,9 +2457,13 @@ Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErro
if (U_FAILURE(status)) {
return;
}
+ if (status == U_STRING_NOT_TERMINATED_WARNING) {
+ status = U_ZERO_ERROR;
+ }
int32_t bufferLength = uprv_max((int32_t)(uprv_strlen(fullName) + 1), ULOC_FULLNAME_CAPACITY);
int32_t newLength = uloc_setKeywordValue(keywordName, keywordValue, fullName,
bufferLength, &status) + 1;
+ U_ASSERT(status != U_STRING_NOT_TERMINATED_WARNING);
/* Handle the case the current buffer is not enough to hold the new id */
if (status == U_BUFFER_OVERFLOW_ERROR) {
U_ASSERT(newLength > bufferLength);
@@ -2476,6 +2480,7 @@ Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErro
fullName = newFullName;
status = U_ZERO_ERROR;
uloc_setKeywordValue(keywordName, keywordValue, fullName, newLength, &status);
+ U_ASSERT(status != U_STRING_NOT_TERMINATED_WARNING);
} else {
U_ASSERT(newLength <= bufferLength);
}
diff --git a/source/common/uloc.cpp b/source/common/uloc.cpp
index 522f33db..ebfbb506 100644
--- a/source/common/uloc.cpp
+++ b/source/common/uloc.cpp
@@ -877,6 +877,9 @@ uloc_setKeywordValue(const char* keywordName,
if(U_FAILURE(*status)) {
return -1;
}
+ if (*status == U_STRING_NOT_TERMINATED_WARNING) {
+ *status = U_ZERO_ERROR;
+ }
if (keywordName == NULL || keywordName[0] == 0 || bufferCapacity <= 1) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
@@ -914,6 +917,7 @@ uloc_setKeywordValue(const char* keywordName,
startSearchHere = (char*)locale_getKeywordsStart(buffer);
if(startSearchHere == NULL || (startSearchHere[1]==0)) {
if(keywordValueLen == 0) { /* no keywords = nothing to remove */
+ U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return bufLen;
}
@@ -933,6 +937,7 @@ uloc_setKeywordValue(const char* keywordName,
startSearchHere += keywordNameLen;
*startSearchHere++ = '=';
uprv_strcpy(startSearchHere, keywordValueBuffer);
+ U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return needLen;
} /* end shortcut - no @ */
@@ -1047,13 +1052,27 @@ uloc_setKeywordValue(const char* keywordName,
if (!handledInputKeyAndValue || U_FAILURE(*status)) {
/* if input key/value specified removal of a keyword not present in locale, or
* there was an error in CharString.append, leave original locale alone. */
+ U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return bufLen;
}
// needLen = length of the part before '@'
needLen = (int32_t)(startSearchHere - buffer);
- return needLen + updatedKeysAndValues.extract(
+ // Check to see can we fit the startSearchHere, if not, return
+ // U_BUFFER_OVERFLOW_ERROR without copy updatedKeysAndValues into it.
+ // We do this because this API function does not behave like most others:
+ // It promises never to set a U_STRING_NOT_TERMINATED_WARNING.
+ // When the contents fits but without the terminating NUL, in this case we need to not change
+ // the buffer contents and return with a buffer overflow error.
+ int32_t appendLength = updatedKeysAndValues.length();
+ if (appendLength >= bufferCapacity - needLen) {
+ *status = U_BUFFER_OVERFLOW_ERROR;
+ return needLen + appendLength;
+ }
+ needLen += updatedKeysAndValues.extract(
startSearchHere, bufferCapacity - needLen, *status);
+ U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
+ return needLen;
}
/* ### ID parsing implementation **************************************************/