libroot: Fix ICU locale implementation of wcsxfrm.
* The "size" parameter is the size of "out" not "in", and the return size_t parameter is supposed to always have the total amount of wchar_ts needed, not how many are actually used. * In the case where "outSize == 0", we set "requiredSize" and then return. Fixes crashes seen in glib2 Unicode collation routines, which are used in GTK file dialogs. Thanks to PulkoMandy for glancing at this.
This commit is contained in:
@@ -33,7 +33,7 @@ public:
|
||||
status_t Wcscoll(const wchar_t* a, const wchar_t* b,
|
||||
int& out);
|
||||
status_t Wcsxfrm(wchar_t* out, const wchar_t* in,
|
||||
size_t size, size_t& outSize);
|
||||
size_t outSize, size_t& requiredSize);
|
||||
|
||||
private:
|
||||
status_t _ToUnicodeString(const char* in,
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
virtual status_t Wcscoll(const wchar_t* a, const wchar_t* b,
|
||||
int& out);
|
||||
virtual status_t Wcsxfrm(wchar_t* out, const wchar_t* in,
|
||||
size_t size, size_t& outSize);
|
||||
size_t outSize, size_t& requiredSize);
|
||||
|
||||
virtual status_t TZSet(const char* timeZoneID, const char* tz);
|
||||
virtual status_t Localtime(const time_t* inTime,
|
||||
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
virtual status_t Wcscoll(const wchar_t* a, const wchar_t* b,
|
||||
int& out) = 0;
|
||||
virtual status_t Wcsxfrm(wchar_t* out, const wchar_t* in,
|
||||
size_t size, size_t& outSize) = 0;
|
||||
size_t outSize, size_t& requiredSize) = 0;
|
||||
|
||||
virtual status_t TZSet(const char* timeZoneID,
|
||||
const char* tz) = 0;
|
||||
|
||||
@@ -174,18 +174,18 @@ ICUCollateData::Wcscoll(const wchar_t* a, const wchar_t* b, int& result)
|
||||
|
||||
|
||||
status_t
|
||||
ICUCollateData::Wcsxfrm(wchar_t* out, const wchar_t* in, size_t size,
|
||||
size_t& outSize)
|
||||
ICUCollateData::Wcsxfrm(wchar_t* out, const wchar_t* in, size_t outSize,
|
||||
size_t& requiredSize)
|
||||
{
|
||||
if (in == NULL) {
|
||||
outSize = 0;
|
||||
requiredSize = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (fCollator == NULL || strcmp(fPosixLocaleName, "POSIX") == 0) {
|
||||
// handle POSIX here as the collator ICU uses for that (english) is
|
||||
// incompatible in too many ways
|
||||
outSize = wcslcpy(out, in, size);
|
||||
requiredSize = wcslcpy(out, in, outSize);
|
||||
for (const wchar_t* inIter = in; *inIter != 0; ++inIter) {
|
||||
if (*inIter > 127)
|
||||
return B_BAD_VALUE;
|
||||
@@ -194,10 +194,13 @@ ICUCollateData::Wcsxfrm(wchar_t* out, const wchar_t* in, size_t size,
|
||||
}
|
||||
|
||||
UnicodeString unicodeIn = UnicodeString::fromUTF32((UChar32*)in, -1);
|
||||
size_t requiredSize = fCollator->getSortKey(unicodeIn, NULL, 0);
|
||||
requiredSize = fCollator->getSortKey(unicodeIn, NULL, 0);
|
||||
|
||||
if (outSize == 0)
|
||||
return B_OK;
|
||||
|
||||
uint8_t* buffer = (uint8_t*)out;
|
||||
outSize = fCollator->getSortKey(unicodeIn, buffer, requiredSize);
|
||||
fCollator->getSortKey(unicodeIn, buffer, outSize);
|
||||
|
||||
// convert 1-byte characters to 4-byte wide characters:
|
||||
for (size_t i = 0; i < outSize; ++i)
|
||||
|
||||
@@ -308,12 +308,12 @@ ICULocaleBackend::Wcscoll(const wchar_t* a, const wchar_t* b, int& result)
|
||||
|
||||
|
||||
status_t
|
||||
ICULocaleBackend::Wcsxfrm(wchar_t* out, const wchar_t* in, size_t size,
|
||||
size_t& outSize)
|
||||
ICULocaleBackend::Wcsxfrm(wchar_t* out, const wchar_t* in, size_t outSize,
|
||||
size_t& requiredSize)
|
||||
{
|
||||
ErrnoMaintainer errnoMaintainer;
|
||||
|
||||
return fCollateData.Wcsxfrm(out, in, size, outSize);
|
||||
return fCollateData.Wcsxfrm(out, in, outSize, requiredSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user