summarylogtreecommitdiffstats
path: root/CVE-2013-0900.patch
diff options
context:
space:
mode:
authorFranklyn Tackitt2015-08-31 10:37:18 -0700
committerFranklyn Tackitt2015-08-31 10:39:39 -0700
commitb3bab9368bbae43361795c45443f40d83728c772 (patch)
treea6fe27422711fc2ed5ff4cafd287c4f705613654 /CVE-2013-0900.patch
downloadaur-icu48.tar.gz
Initial commit
Diffstat (limited to 'CVE-2013-0900.patch')
-rw-r--r--CVE-2013-0900.patch296
1 files changed, 296 insertions, 0 deletions
diff --git a/CVE-2013-0900.patch b/CVE-2013-0900.patch
new file mode 100644
index 00000000000..710d3e9d4a0
--- /dev/null
+++ b/CVE-2013-0900.patch
@@ -0,0 +1,296 @@
+Description: CVE-2013-0900: Race condition in ICU.
+ Credit to Google Chrome Security Team (Inferno)
+ Patch taken from backport done by Fedora 17
+Origin: upstream, http://www.icu-project.org/trac/changeset/32865, http://www.icu-project.org/trac/changeset/32908
+Bug-Debian: http://bugs.debian.org/702346
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2013-0900
+
+Index: icu-4.8.1.1/source/common/locid.cpp
+===================================================================
+--- icu-4.8.1.1.orig/source/common/locid.cpp 2013-03-21 11:21:45.053153118 -0400
++++ icu-4.8.1.1/source/common/locid.cpp 2013-03-21 11:21:45.029153121 -0400
+@@ -1,6 +1,6 @@
+ /*
+ **********************************************************************
+- * Copyright (C) 1997-2010, International Business Machines
++ * Copyright (C) 1997-2012, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ **********************************************************************
+ *
+@@ -32,6 +32,7 @@
+
+ #include "unicode/locid.h"
+ #include "unicode/uloc.h"
++#include "mutex.h"
+ #include "umutex.h"
+ #include "uassert.h"
+ #include "cmemory.h"
+@@ -41,6 +42,21 @@
+
+ #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
++U_CDECL_BEGIN
++static UBool U_CALLCONV locale_cleanup(void);
++U_CDECL_END
++
++U_NAMESPACE_BEGIN
++
++static U_NAMESPACE_QUALIFIER Locale *gLocaleCache = NULL;
++
++// gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale.
++static UMTX gDefaultLocaleMutex = 0;
++static UHashtable *gDefaultLocalesHashT = NULL;
++static U_NAMESPACE_QUALIFIER Locale *gDefaultLocale = NULL;
++
++U_NAMESPACE_END
++
+ typedef enum ELocalePos {
+ eENGLISH,
+ eFRENCH,
+@@ -75,10 +91,6 @@
+ UBool valuesToo,
+ UErrorCode *status);
+
+-static U_NAMESPACE_QUALIFIER Locale *gLocaleCache = NULL;
+-static U_NAMESPACE_QUALIFIER Locale *gDefaultLocale = NULL;
+-static UHashtable *gDefaultLocalesHashT = NULL;
+-
+ U_CDECL_BEGIN
+ //
+ // Deleter function for Locales owned by the default Locale hash table/
+@@ -100,24 +112,19 @@
+ if (gDefaultLocalesHashT) {
+ uhash_close(gDefaultLocalesHashT); // Automatically deletes all elements, using deleter func.
+ gDefaultLocalesHashT = NULL;
++ gDefaultLocale = NULL;
+ }
+- else if (gDefaultLocale) {
+- // The cache wasn't created, and only one default locale was created.
+- delete gDefaultLocale;
+- }
+- gDefaultLocale = NULL;
+
+ return TRUE;
+ }
+ U_CDECL_END
+
+ U_NAMESPACE_BEGIN
+-//
+-// locale_set_default_internal.
+-//
+-void locale_set_default_internal(const char *id)
+-{
+- UErrorCode status = U_ZERO_ERROR;
++
++Locale *locale_set_default_internal(const char *id, UErrorCode& status) {
++ // Synchronize this entire function.
++ Mutex lock(&gDefaultLocaleMutex);
++
+ UBool canonicalize = FALSE;
+
+ // If given a NULL string for the locale id, grab the default
+@@ -125,17 +132,10 @@
+ // (Different from most other locale APIs, where a null name means use
+ // the current ICU default locale.)
+ if (id == NULL) {
+- umtx_lock(NULL);
+- id = uprv_getDefaultLocaleID();
+- umtx_unlock(NULL);
++ id = uprv_getDefaultLocaleID(); // This function not thread safe? TODO: verify.
+ canonicalize = TRUE; // always canonicalize host ID
+ }
+
+- // put the locale id into a canonical form,
+- // in preparation for looking up this locale in the hash table of
+- // already-created locale objects.
+- //
+- status = U_ZERO_ERROR;
+ char localeNameBuf[512];
+
+ if (canonicalize) {
+@@ -146,100 +146,37 @@
+ localeNameBuf[sizeof(localeNameBuf)-1] = 0; // Force null termination in event of
+ // a long name filling the buffer.
+ // (long names are truncated.)
++ //
++ if (U_FAILURE(status)) {
++ return gDefaultLocale;
++ }
+
+- // Lazy creation of the hash table itself, if needed.
+- UBool isOnlyLocale;
+- UMTX_CHECK(NULL, (gDefaultLocale == NULL), isOnlyLocale);
+- if (isOnlyLocale) {
+- // We haven't seen this locale id before.
+- // Create a new Locale object for it.
+- Locale *newFirstDefault = new Locale(Locale::eBOGUS);
+- if (newFirstDefault == NULL) {
+- // No way to report errors from here.
+- return;
+- }
+- newFirstDefault->init(localeNameBuf, FALSE);
+- umtx_lock(NULL);
+- if (gDefaultLocale == NULL) {
+- gDefaultLocale = newFirstDefault; // Assignment to gDefaultLocale must happen inside mutex
+- newFirstDefault = NULL;
+- ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
+- }
+- // Else some other thread raced us through here, and set the new Locale.
+- // Use the hash table next.
+- umtx_unlock(NULL);
+- if (newFirstDefault == NULL) {
+- // We were successful in setting the locale, and we were the first one to set it.
+- return;
+- }
+- // else start using the hash table.
+- }
+-
+- // Lazy creation of the hash table itself, if needed.
+- UBool hashTableNeedsInit;
+- UMTX_CHECK(NULL, (gDefaultLocalesHashT == NULL), hashTableNeedsInit);
+- if (hashTableNeedsInit) {
+- status = U_ZERO_ERROR;
+- UHashtable *tHashTable = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
++ if (gDefaultLocalesHashT == NULL) {
++ gDefaultLocalesHashT = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
+ if (U_FAILURE(status)) {
+- return;
+- }
+- uhash_setValueDeleter(tHashTable, deleteLocale);
+- umtx_lock(NULL);
+- if (gDefaultLocalesHashT == NULL) {
+- gDefaultLocalesHashT = tHashTable;
+- ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
+- } else {
+- uhash_close(tHashTable);
+- hashTableNeedsInit = FALSE;
++ return gDefaultLocale;
+ }
+- umtx_unlock(NULL);
++ uhash_setValueDeleter(gDefaultLocalesHashT, deleteLocale);
++ ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
+ }
+
+- // Hash table lookup, key is the locale full name
+- umtx_lock(NULL);
+ Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf);
+- if (newDefault != NULL) {
+- // We have the requested locale in the hash table already.
+- // Just set it as default. Inside the mutex lock, for those troublesome processors.
+- gDefaultLocale = newDefault;
+- umtx_unlock(NULL);
+- } else {
+- umtx_unlock(NULL);
+- // We haven't seen this locale id before.
+- // Create a new Locale object for it.
++ if (newDefault == NULL) {
+ newDefault = new Locale(Locale::eBOGUS);
+ if (newDefault == NULL) {
+- // No way to report errors from here.
+- return;
++ status = U_MEMORY_ALLOCATION_ERROR;
++ return gDefaultLocale;
+ }
+ newDefault->init(localeNameBuf, FALSE);
+-
+- // Add newly created Locale to the hash table of default Locales
+- const char *key = newDefault->getName();
+- U_ASSERT(uprv_strcmp(key, localeNameBuf) == 0);
+- umtx_lock(NULL);
+- Locale *hashTableVal = (Locale *)uhash_get(gDefaultLocalesHashT, key);
+- if (hashTableVal == NULL) {
+- if (hashTableNeedsInit) {
+- // This is the second request to set the locale.
+- // Cache the first one.
+- uhash_put(gDefaultLocalesHashT, (void *)gDefaultLocale->getName(), gDefaultLocale, &status);
+- }
+- uhash_put(gDefaultLocalesHashT, (void *)key, newDefault, &status);
+- gDefaultLocale = newDefault;
+- // ignore errors from hash table insert. (Couldn't do anything anyway)
+- // We can still set the default Locale,
+- // it just wont be cached, and will eventually leak.
+- } else {
+- // Some other thread raced us through here, and got the new Locale
+- // into the hash table before us. Use that one.
+- gDefaultLocale = hashTableVal; // Assignment to gDefaultLocale must happen inside mutex
+- delete newDefault;
++ uhash_put(gDefaultLocalesHashT, (char*) newDefault->getName(), newDefault, &status);
++ if (U_FAILURE(status)) {
++ return gDefaultLocale;
+ }
+- umtx_unlock(NULL);
+ }
++ gDefaultLocale = newDefault;
++ return gDefaultLocale;
+ }
++
+ U_NAMESPACE_END
+
+ /* sfb 07/21/99 */
+@@ -247,7 +184,8 @@
+ locale_set_default(const char *id)
+ {
+ U_NAMESPACE_USE
+- locale_set_default_internal(id);
++ UErrorCode status = U_ZERO_ERROR;
++ locale_set_default_internal(id, status);
+ }
+ /* end */
+
+@@ -255,7 +193,6 @@
+ locale_get_default(void)
+ {
+ U_NAMESPACE_USE
+-
+ return Locale::getDefault().getName();
+ }
+
+@@ -661,19 +598,14 @@
+ const Locale& U_EXPORT2
+ Locale::getDefault()
+ {
+- const Locale *retLocale;
+- UMTX_CHECK(NULL, gDefaultLocale, retLocale);
+- if (retLocale == NULL) {
+- locale_set_default_internal(NULL);
+- umtx_lock(NULL);
+- // Need a mutex in case some other thread set a new
+- // default inbetween when we set and when we get the new default. For
+- // processors with weak memory coherency, we might not otherwise see all
+- // of the newly created new default locale.
+- retLocale = gDefaultLocale;
+- umtx_unlock(NULL);
++ {
++ Mutex lock(&gDefaultLocaleMutex);
++ if (gDefaultLocale != NULL) {
++ return *gDefaultLocale;
++ }
+ }
+- return *retLocale;
++ UErrorCode status = U_ZERO_ERROR;
++ return *locale_set_default_internal(NULL, status);
+ }
+
+
+@@ -690,7 +622,7 @@
+ * This is a convenient way to access the default locale caching mechanisms.
+ */
+ const char *localeID = newLocale.getName();
+- locale_set_default_internal(localeID);
++ locale_set_default_internal(localeID, status);
+ }
+
+ Locale U_EXPORT2
+Index: icu-4.8.1.1/source/common/unicode/locid.h
+===================================================================
+--- icu-4.8.1.1.orig/source/common/unicode/locid.h 2013-03-21 11:21:45.053153118 -0400
++++ icu-4.8.1.1/source/common/unicode/locid.h 2013-03-21 11:21:45.041153115 -0400
+@@ -732,7 +732,7 @@
+ * A friend to allow the default locale to be set by either the C or C++ API.
+ * @internal
+ */
+- friend void locale_set_default_internal(const char *);
++ friend Locale *locale_set_default_internal(const char *, UErrorCode& status);
+ };
+
+ inline UBool