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;
|
virtual void Initialize(LocaleDataBridge* dataBridge) = 0;
|
||||||
|
|
||||||
static status_t LoadBackend();
|
static status_t LoadBackend();
|
||||||
static LocaleBackend* CreateBackend();
|
static status_t CreateBackend(LocaleBackend*& backendOut);
|
||||||
static void DestroyBackend(LocaleBackend* instance);
|
static void DestroyBackend(LocaleBackend* instance);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ LoadFunctions()
|
|||||||
static void
|
static void
|
||||||
LoadBackend()
|
LoadBackend()
|
||||||
{
|
{
|
||||||
gGlobalLocaleBackend = LocaleBackend::CreateBackend();
|
LocaleBackend::CreateBackend(gGlobalLocaleBackend);
|
||||||
if (gGlobalLocaleBackend != NULL) {
|
if (gGlobalLocaleBackend != NULL) {
|
||||||
gGlobalLocaleBackend->Initialize(&gGlobalLocaleDataBridge);
|
gGlobalLocaleBackend->Initialize(&gGlobalLocaleDataBridge);
|
||||||
}
|
}
|
||||||
@@ -81,19 +81,20 @@ LocaleBackend::LoadBackend()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LocaleBackend*
|
status_t
|
||||||
LocaleBackend::CreateBackend()
|
LocaleBackend::CreateBackend(LocaleBackend*& backendOut)
|
||||||
{
|
{
|
||||||
if (sCreateInstanceFunc == NULL) {
|
if (sCreateInstanceFunc == NULL) {
|
||||||
pthread_once(&sFunctionsInitOnce, &BPrivate::Libroot::LoadFunctions);
|
pthread_once(&sFunctionsInitOnce, &BPrivate::Libroot::LoadFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sCreateInstanceFunc != NULL) {
|
if (sCreateInstanceFunc != NULL) {
|
||||||
LocaleBackend* backend = sCreateInstanceFunc();
|
backendOut = sCreateInstanceFunc();
|
||||||
return backend;
|
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;
|
return (locale_t)newObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
BPrivate::ErrnoMaintainer errnoMaintainer;
|
|
||||||
|
|
||||||
LocaleBackend*& newBackend = newObj->backend;
|
LocaleBackend*& newBackend = newObj->backend;
|
||||||
LocaleDataBridge*& newDataBridge = newObj->databridge;
|
LocaleDataBridge*& newDataBridge = newObj->databridge;
|
||||||
newBackend = LocaleBackend::CreateBackend();
|
|
||||||
|
status_t status = LocaleBackend::CreateBackend(newBackend);
|
||||||
|
|
||||||
if (newBackend == NULL) {
|
if (newBackend == NULL) {
|
||||||
errno = ENOMEM;
|
errno = status;
|
||||||
delete newObj;
|
delete newObj;
|
||||||
return (locale_t)0;
|
return (locale_t)0;
|
||||||
}
|
}
|
||||||
@@ -69,7 +68,7 @@ duplocale(locale_t l)
|
|||||||
|
|
||||||
if (newDataBridge == NULL) {
|
if (newDataBridge == NULL) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
delete newBackend;
|
LocaleBackend::DestroyBackend(newBackend);
|
||||||
delete newObj;
|
delete newObj;
|
||||||
return (locale_t)0;
|
return (locale_t)0;
|
||||||
}
|
}
|
||||||
@@ -164,9 +163,9 @@ newlocale(int category_mask, const char* locale, locale_t base)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (needBackend) {
|
if (needBackend) {
|
||||||
backend = LocaleBackend::CreateBackend();
|
status_t status = LocaleBackend::CreateBackend(backend);
|
||||||
if (backend == NULL) {
|
if (backend == NULL) {
|
||||||
errno = ENOMEM;
|
errno = status;
|
||||||
if (newObject) {
|
if (newObject) {
|
||||||
delete localeObject;
|
delete localeObject;
|
||||||
}
|
}
|
||||||
@@ -175,7 +174,7 @@ newlocale(int category_mask, const char* locale, locale_t base)
|
|||||||
databridge = new (std::nothrow) LocaleDataBridge(false);
|
databridge = new (std::nothrow) LocaleDataBridge(false);
|
||||||
if (databridge == NULL) {
|
if (databridge == NULL) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
delete backend;
|
LocaleBackend::DestroyBackend(backend);
|
||||||
if (newObject) {
|
if (newObject) {
|
||||||
delete localeObject;
|
delete localeObject;
|
||||||
}
|
}
|
||||||
@@ -228,7 +227,32 @@ uselocale(locale_t newLoc)
|
|||||||
SetCurrentLocaleInfo((LocaleBackendData*)appliedLoc);
|
SetCurrentLocaleInfo((LocaleBackendData*)appliedLoc);
|
||||||
|
|
||||||
if (appliedLoc != NULL) {
|
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 {
|
} else {
|
||||||
gGlobalLocaleDataBridge.ApplyToCurrentThread();
|
gGlobalLocaleDataBridge.ApplyToCurrentThread();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user