diff --git a/include/_ctype.h b/include/_ctype.h --- a/include/_ctype.h +++ b/include/_ctype.h @@ -85,8 +85,6 @@ #define __inline #endif -extern int __mb_sb_limit; - /* * Use inline functions if we are allowed to and the compiler supports them. */ @@ -95,6 +93,11 @@ #include +__BEGIN_DECLS +int ___mb_sb_limit(void); +__END_DECLS +#define __MB_SB_LIMIT (___mb_sb_limit()) + static __inline int __maskrune(__ct_rune_t _c, unsigned long _f) { @@ -105,7 +108,7 @@ static __inline int __sbmaskrune(__ct_rune_t _c, unsigned long _f) { - return (_c < 0 || _c >= __mb_sb_limit) ? 0 : + return (_c < 0 || _c >= __MB_SB_LIMIT) ? 0 : _CurrentRuneLocale->__runetype[_c] & _f; } @@ -138,7 +141,7 @@ static __inline __ct_rune_t __sbtoupper(__ct_rune_t _c) { - return (_c < 0 || _c >= __mb_sb_limit) ? _c : + return (_c < 0 || _c >= __MB_SB_LIMIT) ? _c : _CurrentRuneLocale->__mapupper[_c]; } @@ -152,7 +155,7 @@ static __inline __ct_rune_t __sbtolower(__ct_rune_t _c) { - return (_c < 0 || _c >= __mb_sb_limit) ? _c : + return (_c < 0 || _c >= __MB_SB_LIMIT) ? _c : _CurrentRuneLocale->__maplower[_c]; } diff --git a/lib/libc/locale/Symbol.map b/lib/libc/locale/Symbol.map --- a/lib/libc/locale/Symbol.map +++ b/lib/libc/locale/Symbol.map @@ -208,6 +208,10 @@ mbrtoc32_l; }; +FBSD_1.8 { + ___mb_sb_limit; +}; + FBSDprivate_1.0 { _PathLocale; __detect_path_locale; diff --git a/lib/libc/locale/runetype.c b/lib/libc/locale/runetype.c --- a/lib/libc/locale/runetype.c +++ b/lib/libc/locale/runetype.c @@ -87,3 +87,9 @@ FIX_LOCALE(locale); return XLOCALE_CTYPE(locale)->__mb_cur_max; } + +int +___mb_sb_limit(void) +{ + return (XLOCALE_CTYPE(__get_locale())->__mb_sb_limit); +} diff --git a/lib/libc/tests/locale/newlocale_test.c b/lib/libc/tests/locale/newlocale_test.c --- a/lib/libc/tests/locale/newlocale_test.c +++ b/lib/libc/tests/locale/newlocale_test.c @@ -27,6 +27,7 @@ #include +#include #include #include @@ -91,7 +92,6 @@ * The issue is cosmetic only as all three have empty collate parts, but we need * to correctly report the one in use in any case. */ - ATF_TC_WITHOUT_HEAD(newlocale_c_posix_cu8_test); ATF_TC_BODY(newlocale_c_posix_cu8_test, tc) { @@ -103,9 +103,33 @@ do_locale_switch("C.UTF-8", "POSIX"); } +/* + * PR 265950: Check that global locale set using setlocale() does not affect + * isctype functions behavior for per-thread locales. + */ +ATF_TC_WITHOUT_HEAD(newlocale_setlocale_isctype); +ATF_TC_BODY(newlocale_setlocale_isctype, tc) +{ + locale_t l; + + /* Use C.UTF-8 as global locale which sets __mb_sb_limit to 128 */ + ATF_REQUIRE(setlocale(LC_ALL, "C.UTF-8") != NULL); + /* + * Use en_US.ISO8859-1 as thread locale (don't really need separate + * thread here) which needs __mb_sb_limit to be 256 for the isupper() + * test below to succeed. + */ + l = newlocale(LC_ALL_MASK, "en_US.ISO8859-1", NULL); + ATF_REQUIRE(l != (locale_t)NULL); + (void) uselocale(l); + /* 0xC0 is "upper" in ISO8859-1 and is illegal character in UTF-8 */ + ATF_REQUIRE(isupper(0xC0) == 1); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, newlocale_c_posix_cu8_test); + ATF_TP_ADD_TC(tp, newlocale_setlocale_isctype); return (atf_no_error()); } diff --git a/usr.bin/localedef/Makefile b/usr.bin/localedef/Makefile --- a/usr.bin/localedef/Makefile +++ b/usr.bin/localedef/Makefile @@ -1,6 +1,7 @@ PROG= localedef -SRCS= charmap.c \ +SRCS= ctypedefs.h \ + charmap.c \ collate.c \ ctype.c \ localedef.c \ @@ -16,8 +17,6 @@ ${SRCS:M*.c}: parser.h parser.h: parser.y -IGNORE_PRAGMA= yes - CFLAGS+= -I. -I${.CURDIR} .if defined(BOOTSTRAPPING) CFLAGS+= -I${.CURDIR}/bootstrap @@ -25,4 +24,8 @@ CFLAGS+= -I${SRCTOP}/lib/libc/locale CFLAGS+= -I${SRCTOP}/lib/libc/stdtime +CLEANFILES+= ctypedefs.h +ctypedefs.h: ${SRCTOP}/include/_ctype.h + sed -n '/^#define\t_CTYPE_.*$$/p' ${.ALLSRC} >${.TARGET} + .include diff --git a/usr.bin/localedef/bootstrap/_ctype.h b/usr.bin/localedef/bootstrap/_ctype.h deleted file mode 100644 --- a/usr.bin/localedef/bootstrap/_ctype.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright 2018-2020 Alex Richardson - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory (Department of Computer Science and - * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the - * DARPA SSITH research programme. - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) - * ("CTSRD"), as part of the DARPA CRASH research programme. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * We have to ensure that we use the same constants as the target system when - * bootstrapping localedef so that we generate compatible databases. - */ -#ifndef __FreeBSD__ -typedef int __ct_rune_t; /* arg type for ctype funcs */ -typedef __ct_rune_t __rune_t; /* rune_t (see above) */ -typedef __ct_rune_t __wint_t; /* wint_t (see above) */ -#endif -#include "../../include/_ctype.h" diff --git a/usr.bin/localedef/ctype.c b/usr.bin/localedef/ctype.c --- a/usr.bin/localedef/ctype.c +++ b/usr.bin/localedef/ctype.c @@ -32,6 +32,9 @@ /* * LC_CTYPE database generation routines for localedef. */ + +#include "ctypedefs.h" + #include #include @@ -45,12 +48,8 @@ #include "localedef.h" #include "parser.h" -/* Always include the defines for the target: */ -#define _DONT_USE_CTYPE_INLINE_ /* Avoid dependencies on runetype.h */ -#include "_ctype.h" #include "runefile.h" - /* Needed for bootstrapping, _CTYPE_N */ #ifndef _CTYPE_N #define _CTYPE_N 0x00400000L