libs/posix: Fix NULL pointer in uselocale
uselocale now attempts to create a backend and a databrige. If the attempt fails due to a missing libroot-addon-icu, uselocale does nothing (to support applications calling uselocale during startup to enforce the C locale). Else, uselocale will fail with ENOMEM. LocaleBackend::CreateBackend() has been modified to return a status_t that indicates whether NULL is returned due to out of memory (B_NO_MEMORY) or due to being unable to load the ICU addon (B_MISSING_LIBRARY). Change-Id: I0f62ebde5890364c64e6694ec58d38de43ec6841 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5505 Tested-by: Commit checker robot <[email protected]> Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
b9643e557d
commit
d02c0bade7
@@ -187,7 +187,7 @@ public:
|
||||
virtual void Initialize(LocaleDataBridge* dataBridge) = 0;
|
||||
|
||||
static status_t LoadBackend();
|
||||
static LocaleBackend* CreateBackend();
|
||||
static status_t CreateBackend(LocaleBackend*& backendOut);
|
||||
static void DestroyBackend(LocaleBackend* instance);
|
||||
};
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ LoadFunctions()
|
||||
static void
|
||||
LoadBackend()
|
||||
{
|
||||
gGlobalLocaleBackend = LocaleBackend::CreateBackend();
|
||||
LocaleBackend::CreateBackend(gGlobalLocaleBackend);
|
||||
if (gGlobalLocaleBackend != NULL) {
|
||||
gGlobalLocaleBackend->Initialize(&gGlobalLocaleDataBridge);
|
||||
}
|
||||
@@ -81,19 +81,20 @@ LocaleBackend::LoadBackend()
|
||||
}
|
||||
|
||||
|
||||
LocaleBackend*
|
||||
LocaleBackend::CreateBackend()
|
||||
status_t
|
||||
LocaleBackend::CreateBackend(LocaleBackend*& backendOut)
|
||||
{
|
||||
if (sCreateInstanceFunc == NULL) {
|
||||
pthread_once(&sFunctionsInitOnce, &BPrivate::Libroot::LoadFunctions);
|
||||
}
|
||||
|
||||
if (sCreateInstanceFunc != NULL) {
|
||||
LocaleBackend* backend = sCreateInstanceFunc();
|
||||
return backend;
|
||||
backendOut = sCreateInstanceFunc();
|
||||
return backendOut != NULL ? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
backendOut = NULL;
|
||||
return B_MISSING_LIBRARY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -53,14 +53,13 @@ duplocale(locale_t l)
|
||||
return (locale_t)newObj;
|
||||
}
|
||||
|
||||
BPrivate::ErrnoMaintainer errnoMaintainer;
|
||||
|
||||
LocaleBackend*& newBackend = newObj->backend;
|
||||
LocaleDataBridge*& newDataBridge = newObj->databridge;
|
||||
newBackend = LocaleBackend::CreateBackend();
|
||||
|
||||
status_t status = LocaleBackend::CreateBackend(newBackend);
|
||||
|
||||
if (newBackend == NULL) {
|
||||
errno = ENOMEM;
|
||||
errno = status;
|
||||
delete newObj;
|
||||
return (locale_t)0;
|
||||
}
|
||||
@@ -69,7 +68,7 @@ duplocale(locale_t l)
|
||||
|
||||
if (newDataBridge == NULL) {
|
||||
errno = ENOMEM;
|
||||
delete newBackend;
|
||||
LocaleBackend::DestroyBackend(newBackend);
|
||||
delete newObj;
|
||||
return (locale_t)0;
|
||||
}
|
||||
@@ -164,9 +163,9 @@ newlocale(int category_mask, const char* locale, locale_t base)
|
||||
}
|
||||
}
|
||||
if (needBackend) {
|
||||
backend = LocaleBackend::CreateBackend();
|
||||
status_t status = LocaleBackend::CreateBackend(backend);
|
||||
if (backend == NULL) {
|
||||
errno = ENOMEM;
|
||||
errno = status;
|
||||
if (newObject) {
|
||||
delete localeObject;
|
||||
}
|
||||
@@ -175,7 +174,7 @@ newlocale(int category_mask, const char* locale, locale_t base)
|
||||
databridge = new (std::nothrow) LocaleDataBridge(false);
|
||||
if (databridge == NULL) {
|
||||
errno = ENOMEM;
|
||||
delete backend;
|
||||
LocaleBackend::DestroyBackend(backend);
|
||||
if (newObject) {
|
||||
delete localeObject;
|
||||
}
|
||||
@@ -228,7 +227,32 @@ uselocale(locale_t newLoc)
|
||||
SetCurrentLocaleInfo((LocaleBackendData*)appliedLoc);
|
||||
|
||||
if (appliedLoc != NULL) {
|
||||
((LocaleBackendData*)appliedLoc)->databridge->ApplyToCurrentThread();
|
||||
LocaleDataBridge*& databridge = ((LocaleBackendData*)appliedLoc)->databridge;
|
||||
// Happens when appliedLoc represents the C locale.
|
||||
if (databridge == NULL) {
|
||||
LocaleBackend*& backend = ((LocaleBackendData*)appliedLoc)->backend;
|
||||
status_t status = LocaleBackend::CreateBackend(backend);
|
||||
if (backend == NULL) {
|
||||
if (status == B_MISSING_LIBRARY) {
|
||||
// This means libroot-addon-icu is not available.
|
||||
// Therefore, the global locale is still the C locale
|
||||
// and cannot be set to any other locale. Do nothing.
|
||||
return oldLoc;
|
||||
}
|
||||
errno = status;
|
||||
return (locale_t)0;
|
||||
}
|
||||
|
||||
databridge = new (std::nothrow) LocaleDataBridge(false);
|
||||
if (databridge == NULL) {
|
||||
LocaleBackend::DestroyBackend(backend);
|
||||
errno = ENOMEM;
|
||||
return (locale_t)0;
|
||||
}
|
||||
|
||||
backend->Initialize(databridge);
|
||||
}
|
||||
databridge->ApplyToCurrentThread();
|
||||
} else {
|
||||
gGlobalLocaleDataBridge.ApplyToCurrentThread();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user