/* Test if the locale id has BCP47 u extension and does not have '@' */
#define _hasBCP47Extension(id) (id && uprv_strstr(id, "@") == NULL && getShortestSubtagLength(localeID) == 1)
/* Converts the BCP47 id to Unicode id. Does nothing to id if conversion fails */
-static int32_t _ConvertBCP47(
- const char*& finalID, const char* id, char* buffer, int32_t length, UErrorCode* err) {
+static const char* _ConvertBCP47(
+ const char* id, char* buffer, int32_t length,
+ UErrorCode* err, int32_t* pLocaleIdSize) {
+ const char* finalID;
int32_t localeIDSize = uloc_forLanguageTag(id, buffer, length, NULL, err);
if (localeIDSize <= 0 || U_FAILURE(*err) || *err == U_STRING_NOT_TERMINATED_WARNING) {
finalID=id;
} else {
finalID=buffer;
}
- return localeIDSize;
+ if (pLocaleIdSize != nullptr) {
+ *pLocaleIdSize = localeIDSize;
+ }
+ return finalID;
}
/* Gets the size of the shortest subtag in the given localeID. */
static int32_t getShortestSubtagLength(const char *localeID) {
}
if (_hasBCP47Extension(localeID)) {
- _ConvertBCP47(tmpLocaleID, localeID, tempBuffer, sizeof(tempBuffer), status);
+ tmpLocaleID = _ConvertBCP47(localeID, tempBuffer,
+ sizeof(tempBuffer), status, nullptr);
} else {
tmpLocaleID=localeID;
}
}
if (_hasBCP47Extension(localeID)) {
- _ConvertBCP47(tmpLocaleID, localeID, tempBuffer, sizeof(tempBuffer), status);
+ tmpLocaleID = _ConvertBCP47(localeID, tempBuffer,
+ sizeof(tempBuffer), status, nullptr);
} else {
if (localeID==NULL) {
- localeID=uloc_getDefault();
+ localeID=uloc_getDefault();
}
tmpLocaleID=localeID;
}
int32_t j, fieldCount=0, scriptSize=0, variantSize=0;
PreflightingLocaleIDBuffer tempBuffer; // if localeID has a BCP47 extension, tmpLocaleID points to this
+ CharString localeIDWithHyphens; // if localeID has a BPC47 extension and have _, tmpLocaleID points to this
const char* origLocaleID;
const char* tmpLocaleID;
const char* keywordAssign = NULL;
const char* separatorIndicator = NULL;
if (_hasBCP47Extension(localeID)) {
- CharString localeIDWithHyphens;
const char* localeIDPtr = localeID;
// convert all underbars to hyphens, unless the "BCP47 extension" comes at the beginning of the string
localeIDPtr = localeIDWithHyphens.data();
}
}
-
+
do {
- tempBuffer.requestedCapacity = _ConvertBCP47(tmpLocaleID, localeIDPtr, tempBuffer.getBuffer(),
- tempBuffer.getCapacity(), err);
+ // After this call tmpLocaleID may point to localeIDPtr which may
+ // point to either localeID or localeIDWithHyphens.data().
+ tmpLocaleID = _ConvertBCP47(localeIDPtr, tempBuffer.getBuffer(),
+ tempBuffer.getCapacity(), err,
+ &(tempBuffer.requestedCapacity));
} while (tempBuffer.needToTryAgain(err));
} else {
if (localeID==NULL) {
}
if (_hasBCP47Extension(localeID)) {
- _ConvertBCP47(tmpLocaleID, localeID, tempBuffer, sizeof(tempBuffer), err);
+ tmpLocaleID =_ConvertBCP47(localeID, tempBuffer, sizeof(tempBuffer), err, nullptr);
} else {
if (localeID==NULL) {
localeID=uloc_getDefault();
TESTCASE(TestKeywordSet);
TESTCASE(TestKeywordSetError);
TESTCASE(TestDisplayKeywords);
+ TESTCASE(TestCanonicalization21749StackUseAfterScope);
TESTCASE(TestDisplayKeywordValues);
TESTCASE(TestGetBaseName);
#if !UCONFIG_NO_FILE_IO
}
}
+static void TestCanonicalization21749StackUseAfterScope(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ char buffer[256];
+ const char* input = "- _";
+ uloc_canonicalize(input, buffer, -1, &status);
+ if (U_SUCCESS(status)) {
+ log_err("FAIL: uloc_canonicalize(%s) => %s, expected U_FAILURE()\n",
+ input, u_errorName(status));
+ return;
+ }
+}
+
static void TestDisplayKeywords(void)
{
int32_t i;