From: John Marino Date: Sat, 11 Jul 2015 09:52:54 +0000 (+0200) Subject: xlocale: Fix potential segfault X-Git-Tag: v4.3.1~203 X-Git-Url: https://gitweb.dragonflybsd.org/~tuxillo/dragonfly.git/commitdiff_plain/bf0d950af810c072318374249db960bc2121a540 xlocale: Fix potential segfault It was possible for locale and rune locale to become out of sync causing mb* and similar functions to be called with the wrong data, including with a null pointer. Unfortunately, this still does not solve the gfortran testsuite failure related to newlocale usage. Taken-from: FreeBSD SVN 264038 (2 APR 2014) --- diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c index 726f842b8f..4e0f8ca69c 100644 --- a/lib/libc/locale/setrunelocale.c +++ b/lib/libc/locale/setrunelocale.c @@ -34,7 +34,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: head/lib/libc/locale/setrunelocale.c 244126 2012-12-11 22:52:56Z jilles $ + * $FreeBSD: head/lib/libc/locale/setrunelocale.c 264038 2014-04-02 11:10:46Z theraven $ */ @@ -202,6 +202,8 @@ __set_thread_rune_locale(locale_t loc) if (loc == NULL) { _ThreadRuneLocale = &_DefaultRuneLocale; + } else if (loc == LC_GLOBAL_LOCALE) { + _ThreadRuneLocale = 0; } else { _ThreadRuneLocale = XLOCALE_CTYPE(loc)->runes; } diff --git a/lib/libc/locale/xlocale.c b/lib/libc/locale/xlocale.c index 695e435b99..c24b776200 100644 --- a/lib/libc/locale/xlocale.c +++ b/lib/libc/locale/xlocale.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: head/lib/libc/locale/xlocale.c 232498 2012-03-04 15:31:13Z theraven $ + * $FreeBSD: head/lib/libc/locale/xlocale.c 264038 2014-04-02 11:10:46Z theraven $ */ #include @@ -154,23 +154,24 @@ __get_locale(void) static void set_thread_locale(locale_t loc) { + locale_t l = (loc == LC_GLOBAL_LOCALE) ? 0 : loc; _once(&once_control, init_key); - if (NULL != loc) { - xlocale_retain((struct xlocale_refcounted*)loc); + if (NULL != l) { + xlocale_retain((struct xlocale_refcounted*)l); } locale_t old = pthread_getspecific(locale_info_key); - if ((NULL != old) && (loc != old)) { + if ((NULL != old) && (l != old)) { xlocale_release((struct xlocale_refcounted*)old); } if (fake_tls) { - thread_local_locale = loc; + thread_local_locale = l; } else { - pthread_setspecific(locale_info_key, loc); + pthread_setspecific(locale_info_key, l); } #ifndef __NO_TLS - __thread_locale = loc; + __thread_locale = l; __set_thread_rune_locale(loc); #endif } @@ -361,9 +362,6 @@ locale_t uselocale(locale_t loc) { locale_t old = get_thread_locale(); if (NULL != loc) { - if (LC_GLOBAL_LOCALE == loc) { - loc = NULL; - } set_thread_locale(loc); } return (old ? old : LC_GLOBAL_LOCALE);