Bug 188036 - mblen(3) in EUC locales causes crash and segmentation fault.
Summary: mblen(3) in EUC locales causes crash and segmentation fault.
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: standards (show other bugs)
Version: 9.2-RELEASE
Hardware: Any Any
: Normal Affects Only Me
Assignee: FreeBSD Release Engineering
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-03-28 22:30 UTC by Tomohisa Tanaka
Modified: 2015-07-07 14:39 UTC (History)
3 users (show)

See Also:
delphij: mfc-stable10+
delphij: mfc-stable9+
delphij: mfc-stable8-


Attachments
file.diff (448 bytes, patch)
2014-03-28 22:30 UTC, Tomohisa Tanaka
no flags Details | Diff
report1.txt (871 bytes, text/plain; charset=US-ASCII)
2014-03-31 17:01 UTC, Tomohisa Tanaka
no flags Details
report2.txt (2.32 KB, text/plain; charset=US-ASCII)
2014-03-31 17:01 UTC, Tomohisa Tanaka
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tomohisa Tanaka 2014-03-28 22:30:00 UTC
Calling function mblen(3) in EUC locales results in crash and
segmentation fault.  To repeat the problem, both setlocale(3) and
uselocale(3) must be called before calling mblen(3).

I think it is because the value of _CurrentRuneLocale->__variable in
/usr/src/lib/libc/locale/euc.c is always NULL after calling both
setlocale(3) and uselocale(3).

Fix: diff -ur /usr/src/lib/libc/locale/euc.c locale/euc.c
--- /usr/src/lib/libc/locale/euc.c	2013-09-27 10:07:50.000000000 +0900
+++ locale/euc.c	2014-03-29 06:16:10.000000000 +0900
@@ -134,7 +134,8 @@
 	return (ps == NULL || ((const _EucState *)ps)->want == 0);
 }
 
-#define	CEI	((_EucInfo *)(_CurrentRuneLocale->__variable))
+#define	CEI	\
+	((_EucInfo *)(XLOCALE_CTYPE(__get_locale())->runes->__variable))
 
 #define	_SS2	0x008e
 #define	_SS3	0x008f



Patch attached with submission follows:
How-To-Repeat: % cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <xlocale.h>

int
main(void)
{
  printf("setlocale: %s\n", setlocale(LC_ALL, ""));

  locale_t newLocale = newlocale(LC_ALL_MASK, "C", NULL);
  locale_t oldLocale = uselocale(newLocale);
  /* ... */
  uselocale(oldLocale);

  printf("%d\n", mblen("a", 1));
  return 0;
}
% gcc -g3 -std=c99 main.c
% setenv LC_MESSAGES C
% env LANG=zh_CN.eucCN ./a.out
setlocale: zh_CN.eucCN/zh_CN.eucCN/zh_CN.eucCN/zh_CN.eucCN/zh_CN.eucCN/C
Segmentation fault (core dumped)
% env LANG=ko_KR.eucKR ./a.out
setlocale: ko_KR.eucKR/ko_KR.eucKR/ko_KR.eucKR/ko_KR.eucKR/ko_KR.eucKR/C
Segmentation fault (core dumped)
% env LANG=ja_JP.eucJP ./a.out
setlocale: ja_JP.eucJP/ja_JP.eucJP/ja_JP.eucJP/ja_JP.eucJP/ja_JP.eucJP/C
Segmentation fault (core dumped)
% env LANG=ja_JP.UTF-8 ./a.out
setlocale: ja_JP.UTF-8/ja_JP.UTF-8/ja_JP.UTF-8/ja_JP.UTF-8/ja_JP.UTF-8/C
1
Comment 1 David Chisnall freebsd_committer 2014-03-31 10:03:57 UTC
I think the fix should actually be:

Index: locale/euc.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- locale/euc.c	(revision 263226)
+++ locale/euc.c	(working copy)
@@ -134,7 +134,7 @@
 	return (ps =3D=3D NULL || ((const _EucState *)ps)->want =3D=3D =
0);
 }
=20
-#define	CEI	((_EucInfo *)(_CurrentRuneLocale->__variable))
+#define	CEI	((_EucInfo =
*)(__getCurrentRuneLocale()->__variable))
=20
 #define	_SS2	0x008e
 #define	_SS3	0x008f



Please can you test this and let me know if it fixes it for you?

David=
Comment 2 David Chisnall freebsd_committer 2014-03-31 10:57:01 UTC
Actually, I'm not sure how this bug can manifest, unless you've somehow =
built libc with the wrong headers.  In runtype.h (which is included in =
euc.c), we have this:

#define _CurrentRuneLocale (__getCurrentRuneLocale())

So these two versions should expand to the same thing. =20

David
Comment 3 dfilter service freebsd_committer 2014-04-02 12:10:50 UTC
Author: theraven
Date: Wed Apr  2 11:10:46 2014
New Revision: 264038
URL: http://svnweb.freebsd.org/changeset/base/264038

Log:
  Fix an issue where the locale and rune locale could become out of sync,
  causing mb* functions (and similar) to be called with the wrong data
  (possibly a null pointer, causing a crash).
  
  PR:		standards/188036
  MFC after:	1 week

Modified:
  head/lib/libc/locale/setrunelocale.c
  head/lib/libc/locale/xlocale.c

Modified: head/lib/libc/locale/setrunelocale.c
==============================================================================
--- head/lib/libc/locale/setrunelocale.c	Wed Apr  2 10:57:11 2014	(r264037)
+++ head/lib/libc/locale/setrunelocale.c	Wed Apr  2 11:10:46 2014	(r264038)
@@ -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;
 	}

Modified: head/lib/libc/locale/xlocale.c
==============================================================================
--- head/lib/libc/locale/xlocale.c	Wed Apr  2 10:57:11 2014	(r264037)
+++ head/lib/libc/locale/xlocale.c	Wed Apr  2 11:10:46 2014	(r264038)
@@ -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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 4 David Chisnall freebsd_committer 2014-06-09 09:19:54 UTC
In head, needs MFC.
Comment 5 t_uemura 2015-04-28 00:06:00 UTC
Hi. Can someone MFC this? The patch surely fixes the issue on FreeBSD 9.3-STABLE #0 r279827 i386. Thanks.
Comment 6 Xin LI freebsd_committer 2015-06-17 18:49:47 UTC
Take.
Comment 7 commit-hook freebsd_committer 2015-06-17 19:12:45 UTC
A commit references this bug:

Author: delphij
Date: Wed Jun 17 19:12:19 UTC 2015
New revision: 284524
URL: https://svnweb.freebsd.org/changeset/base/284524

Log:
  MFC r264038 (theraven):

  Fix an issue where the locale and rune locale could become out of sync,
  causing mb* functions (and similar) to be called with the wrong data
  (possibly a null pointer, causing a crash).

  PR:		standards/188036

Changes:
_U  stable/10/
  stable/10/lib/libc/locale/setrunelocale.c
  stable/10/lib/libc/locale/xlocale.c
Comment 8 commit-hook freebsd_committer 2015-06-17 19:13:47 UTC
A commit references this bug:

Author: delphij
Date: Wed Jun 17 19:13:14 UTC 2015
New revision: 284525
URL: https://svnweb.freebsd.org/changeset/base/284525

Log:
  MFC r264038 (theraven)

  Fix an issue where the locale and rune locale could become out of sync,
  causing mb* functions (and similar) to be called with the wrong data
  (possibly a null pointer, causing a crash).

  PR:		standards/188036

Changes:
_U  stable/9/lib/libc/
  stable/9/lib/libc/locale/setrunelocale.c
  stable/9/lib/libc/locale/xlocale.c
Comment 9 Xin LI freebsd_committer 2015-06-17 19:15:15 UTC
Note MFC's: 9/ and 10/ were done.  8/ doesn't have xlocale(3) and is therefore not affected.
Comment 10 Glen Barber freebsd_committer 2015-07-07 14:39:36 UTC
Resolved as of EN-15:09.