82b174
Downstream-only patch to introduce the
82b174
/etc/sysconfig/strcasecmp-nonascii configuration file, which switches
82b174
to an implementation of strcasecmp, strcasecmp_l, strncasecmp,
82b174
strncasecmp_l that always performs case-conversion as per tolower.
82b174
82b174
The original glibc 2.17 version of these functions only ignored
82b174
case within the ASCII range due to upstream bug 15736, but it is
82b174
too late to change this regression (compared to Red Hat Enterprise
82b174
Linux 6) in Red Hat Enterprise Linux 7.
82b174
82b174
This patch only covers i686 and x86_64.  s390x is not affected.
82b174
ppc64le would require additional changes.
82b174
82b174
diff --git a/sysdeps/i386/i686/multiarch/init-arch.h b/sysdeps/i386/i686/multiarch/init-arch.h
82b174
index cd2d0befee728b50..60d0eed17d004871 100644
82b174
--- a/sysdeps/i386/i686/multiarch/init-arch.h
82b174
+++ b/sysdeps/i386/i686/multiarch/init-arch.h
82b174
@@ -1 +1,21 @@
82b174
 #include <sysdeps/x86_64/multiarch/init-arch.h>
82b174
+
82b174
+#ifdef __ASSEMBLER__
82b174
+/* Performan an access system call to check whether the configuration
82b174
+  file exists.  If it does, load SYMBOL into %eax and jump to LABEL.  */
82b174
+# define CHECK_STRCASECMP_CONFIG_FILE(symbol, label) \
82b174
+	pushl	%ebx; \
82b174
+	cfi_adjust_cfa_offset (4); \
82b174
+	cfi_rel_offset (%ebx, 0); \
82b174
+	LOAD_PIC_REG (dx); \
82b174
+	movl	$__NR_access, %eax; \
82b174
+	lea	__sysconfig_strcasecmp_nonascii@GOTOFF(%edx), %ebx; \
82b174
+	xor	%ecx, %ecx; \
82b174
+	int	$0x80; \
82b174
+	test	%eax, %eax; \
82b174
+	lea	symbol@GOTOFF(%edx), %eax; \
82b174
+	popl	%ebx; \
82b174
+	cfi_adjust_cfa_offset (-4); \
82b174
+	cfi_restore (%ebx); \
82b174
+	jz	label
82b174
+#endif
82b174
diff --git a/sysdeps/i386/i686/multiarch/strcasecmp-c.c b/sysdeps/i386/i686/multiarch/strcasecmp-c.c
82b174
index 753c6ec84ab9f8ea..b50c527525a347d0 100644
82b174
--- a/sysdeps/i386/i686/multiarch/strcasecmp-c.c
82b174
+++ b/sysdeps/i386/i686/multiarch/strcasecmp-c.c
82b174
@@ -10,3 +10,8 @@ strong_alias (__strcasecmp_nonascii, __strcasecmp_ia32)
82b174
 /* The needs of strcasecmp in libc are minimal, no need to go through
82b174
    the IFUNC.  */
82b174
 strong_alias (__strcasecmp_nonascii, __GI___strcasecmp)
82b174
+
82b174
+/* Used by the assembler IFUNC selectors.  Presence of this file
82b174
+   indicates that the C implementation shall be used.  */
82b174
+const char __sysconfig_strcasecmp_nonascii[] attribute_hidden =
82b174
+  "/etc/sysconfig/strcasecmp-nonascii";
82b174
diff --git a/sysdeps/i386/i686/multiarch/strcasecmp.S b/sysdeps/i386/i686/multiarch/strcasecmp.S
82b174
index 7efef3b1b0545b5d..9c21a2d5d8b713a1 100644
82b174
--- a/sysdeps/i386/i686/multiarch/strcasecmp.S
82b174
+++ b/sysdeps/i386/i686/multiarch/strcasecmp.S
82b174
@@ -23,6 +23,7 @@
82b174
 	.text
82b174
 ENTRY(__strcasecmp)
82b174
 	.type	__strcasecmp, @gnu_indirect_function
82b174
+	CHECK_STRCASECMP_CONFIG_FILE (__strcasecmp_nonascii, 2f)
82b174
 	LOAD_GOT_AND_RTLD_GLOBAL_RO
82b174
 	LOAD_FUNC_GOT_EAX (__strcasecmp_ia32)
82b174
 	HAS_CPU_FEATURE (SSSE3)
82b174
diff --git a/sysdeps/i386/i686/multiarch/strcasecmp_l.S b/sysdeps/i386/i686/multiarch/strcasecmp_l.S
82b174
index 711c09b0dc1fa62e..512e9bd66ed66b23 100644
82b174
--- a/sysdeps/i386/i686/multiarch/strcasecmp_l.S
82b174
+++ b/sysdeps/i386/i686/multiarch/strcasecmp_l.S
82b174
@@ -1,6 +1,7 @@
82b174
 /* Multiple versions of strcasecmp_l
82b174
    All versions must be listed in ifunc-impl-list.c.  */
82b174
 #define STRCMP __strcasecmp_l
82b174
+#define STRCMP_NONASCII __strcasecmp_l_nonascii
82b174
 #define USE_AS_STRCASECMP_L
82b174
 #include "strcmp.S"
82b174
 
82b174
diff --git a/sysdeps/i386/i686/multiarch/strcmp.S b/sysdeps/i386/i686/multiarch/strcmp.S
82b174
index 19967e8db0990c2c..7fc791a18089da6f 100644
82b174
--- a/sysdeps/i386/i686/multiarch/strcmp.S
82b174
+++ b/sysdeps/i386/i686/multiarch/strcmp.S
82b174
@@ -54,6 +54,9 @@
82b174
 	.text
82b174
 ENTRY(STRCMP)
82b174
 	.type	STRCMP, @gnu_indirect_function
82b174
+#if defined (USE_AS_STRCASECMP_L) || defined (USE_AS_STRNCASECMP_L)
82b174
+	CHECK_STRCASECMP_CONFIG_FILE (STRCMP_NONASCII, 2f)
82b174
+#endif
82b174
 	LOAD_GOT_AND_RTLD_GLOBAL_RO
82b174
 	LOAD_FUNC_GOT_EAX (__STRCMP_IA32)
82b174
 	HAS_CPU_FEATURE (SSSE3)
82b174
diff --git a/sysdeps/i386/i686/multiarch/strncase.S b/sysdeps/i386/i686/multiarch/strncase.S
82b174
index 952c7c60994f3023..36495559de590179 100644
82b174
--- a/sysdeps/i386/i686/multiarch/strncase.S
82b174
+++ b/sysdeps/i386/i686/multiarch/strncase.S
82b174
@@ -23,6 +23,7 @@
82b174
 	.text
82b174
 ENTRY(__strncasecmp)
82b174
 	.type	__strncasecmp, @gnu_indirect_function
82b174
+	CHECK_STRCASECMP_CONFIG_FILE (__strncasecmp_nonascii, 2f)
82b174
 	LOAD_GOT_AND_RTLD_GLOBAL_RO
82b174
 	LOAD_FUNC_GOT_EAX (__strncasecmp_ia32)
82b174
 	HAS_CPU_FEATURE (SSSE3)
82b174
diff --git a/sysdeps/i386/i686/multiarch/strncase_l.S b/sysdeps/i386/i686/multiarch/strncase_l.S
82b174
index 8a74ee8574c720ae..b77951b26b98b8c8 100644
82b174
--- a/sysdeps/i386/i686/multiarch/strncase_l.S
82b174
+++ b/sysdeps/i386/i686/multiarch/strncase_l.S
82b174
@@ -1,6 +1,7 @@
82b174
 /* Multiple versions of strncasecmp_l
82b174
    All versions must be listed in ifunc-impl-list.c.  */
82b174
 #define STRCMP __strncasecmp_l
82b174
+#define STRCMP_NONASCII __strncasecmp_l_nonascii
82b174
 #define USE_AS_STRNCASECMP_L
82b174
 #include "strcmp.S"
82b174
 
82b174
diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile
82b174
index c6766bb2b443a28a..d75ec12e6f1237c9 100644
82b174
--- a/sysdeps/x86_64/Makefile
82b174
+++ b/sysdeps/x86_64/Makefile
82b174
@@ -14,7 +14,8 @@ tests += tst-mallocalign1
82b174
 endif
82b174
 
82b174
 ifeq ($(subdir),string)
82b174
-sysdep_routines += cacheinfo strcasecmp_l-nonascii strncase_l-nonascii
82b174
+sysdep_routines += cacheinfo strcasecmp_l-nonascii strncase_l-nonascii \
82b174
+  strcasecmp-nonascii strncase-nonascii
82b174
 gen-as-const-headers += locale-defines.sym
82b174
 endif
82b174
 
82b174
diff --git a/sysdeps/x86_64/multiarch/strcasecmp_l.S b/sysdeps/x86_64/multiarch/strcasecmp_l.S
82b174
index 49f5b9fd952d3cdc..0feefe1ac81cefac 100644
82b174
--- a/sysdeps/x86_64/multiarch/strcasecmp_l.S
82b174
+++ b/sysdeps/x86_64/multiarch/strcasecmp_l.S
82b174
@@ -1,6 +1,7 @@
82b174
 /* Multiple versions of strcasecmp and strcasecmp_l
82b174
    All versions must be listed in ifunc-impl-list.c.  */
82b174
 #define STRCMP __strcasecmp_l
82b174
+#define STRCMP_NONASCII __strcasecmp_l_nonascii
82b174
 #define USE_AS_STRCASECMP_L
82b174
 #include "strcmp.S"
82b174
 
82b174
diff --git a/sysdeps/x86_64/multiarch/strcmp.S b/sysdeps/x86_64/multiarch/strcmp.S
82b174
index 48b4db8c430a514f..ede41c8f61e8b472 100644
82b174
--- a/sysdeps/x86_64/multiarch/strcmp.S
82b174
+++ b/sysdeps/x86_64/multiarch/strcmp.S
82b174
@@ -76,6 +76,17 @@
82b174
 # endif
82b174
 #endif
82b174
 
82b174
+/* Performan an access system call to check whether the configuration
82b174
+  file exists.  If it does, load SYMBOL into %rax and jump to LABEL.  */
82b174
+#define CHECK_STRCASECMP_CONFIG_FILE(symbol, label) \
82b174
+	movl	$__NR_access, %eax; \
82b174
+	leaq	__sysconfig_strcasecmp_nonascii(%rip), %rdi; \
82b174
+	xor	%esi, %esi; \
82b174
+	syscall ; \
82b174
+	test	%eax, %eax; \
82b174
+	leaq 	symbol(%rip), %rax; \
82b174
+	jz	label
82b174
+
82b174
 /* Define multiple versions only for the definition in libc.  Don't
82b174
    define multiple versions for strncmp in static library since we
82b174
    need strncmp before the initialization happened.  */
82b174
@@ -83,6 +94,9 @@
82b174
 	.text
82b174
 ENTRY(STRCMP)
82b174
 	.type	STRCMP, @gnu_indirect_function
82b174
+# if defined (USE_AS_STRCASECMP_L) || defined (USE_AS_STRNCASECMP_L)
82b174
+	CHECK_STRCASECMP_CONFIG_FILE(STRCMP_NONASCII, 2f)
82b174
+# endif
82b174
 	LOAD_RTLD_GLOBAL_RO_RDX
82b174
 	leaq	STRCMP_SSE42(%rip), %rax
82b174
 	HAS_CPU_FEATURE (SSE4_2)
82b174
@@ -97,6 +111,7 @@ END(STRCMP)
82b174
 # ifdef USE_AS_STRCASECMP_L
82b174
 ENTRY(__strcasecmp)
82b174
 	.type	__strcasecmp, @gnu_indirect_function
82b174
+	CHECK_STRCASECMP_CONFIG_FILE(__strcasecmp_nonascii, 2f)
82b174
 	LOAD_RTLD_GLOBAL_RO_RDX
82b174
 #  ifdef HAVE_AVX_SUPPORT
82b174
 	leaq	__strcasecmp_avx(%rip), %rax
82b174
@@ -117,6 +132,7 @@ weak_alias (__strcasecmp, strcasecmp)
82b174
 # ifdef USE_AS_STRNCASECMP_L
82b174
 ENTRY(__strncasecmp)
82b174
 	.type	__strncasecmp, @gnu_indirect_function
82b174
+	CHECK_STRCASECMP_CONFIG_FILE(__strncasecmp_nonascii, 2f)
82b174
 	LOAD_RTLD_GLOBAL_RO_RDX
82b174
 #  ifdef HAVE_AVX_SUPPORT
82b174
 	leaq	__strncasecmp_avx(%rip), %rax
82b174
diff --git a/sysdeps/x86_64/multiarch/strncase_l.S b/sysdeps/x86_64/multiarch/strncase_l.S
82b174
index 9c0149788e9c11b5..259ce6b5ef57e178 100644
82b174
--- a/sysdeps/x86_64/multiarch/strncase_l.S
82b174
+++ b/sysdeps/x86_64/multiarch/strncase_l.S
82b174
@@ -1,6 +1,7 @@
82b174
 /* Multiple versions of strncasecmp and strncasecmp_l
82b174
    All versions must be listed in ifunc-impl-list.c.  */
82b174
 #define STRCMP __strncasecmp_l
82b174
+#define STRCMP_NONASCII __strncasecmp_l_nonascii
82b174
 #define USE_AS_STRNCASECMP_L
82b174
 #include "strcmp.S"
82b174
 
82b174
diff --git a/sysdeps/x86_64/strcasecmp-nonascii.c b/sysdeps/x86_64/strcasecmp-nonascii.c
82b174
new file mode 100644
82b174
index 0000000000000000..7e81a7bdb6f52c47
82b174
--- /dev/null
82b174
+++ b/sysdeps/x86_64/strcasecmp-nonascii.c
82b174
@@ -0,0 +1,13 @@
82b174
+#if IS_IN (libc)
82b174
+# include <string.h>
82b174
+
82b174
+extern int __strcasecmp_nonascii (const char *__s1, const char *__s2);
82b174
+
82b174
+# define __strcasecmp __strcasecmp_nonascii
82b174
+# include <string/strcasecmp.c>
82b174
+
82b174
+/* Used by the assembler IFUNC selectors.  Presence of this file
82b174
+   indicates that the C implementation shall be used.  */
82b174
+const char __sysconfig_strcasecmp_nonascii[] attribute_hidden =
82b174
+  "/etc/sysconfig/strcasecmp-nonascii";
82b174
+#endif
82b174
diff --git a/sysdeps/x86_64/strcasecmp_l-nonascii.c b/sysdeps/x86_64/strcasecmp_l-nonascii.c
82b174
index 30e8969603ea7817..4abd55ae2a54f94a 100644
82b174
--- a/sysdeps/x86_64/strcasecmp_l-nonascii.c
82b174
+++ b/sysdeps/x86_64/strcasecmp_l-nonascii.c
82b174
@@ -1,8 +1,10 @@
82b174
-#include <string.h>
82b174
+#if IS_IN (libc)
82b174
+# include <string.h>
82b174
 
82b174
 extern int __strcasecmp_l_nonascii (const char *__s1, const char *__s2,
82b174
 				    __locale_t __loc);
82b174
 
82b174
-#define __strcasecmp_l __strcasecmp_l_nonascii
82b174
-#define USE_IN_EXTENDED_LOCALE_MODEL    1
82b174
-#include <string/strcasecmp.c>
82b174
+# define __strcasecmp_l __strcasecmp_l_nonascii
82b174
+# define USE_IN_EXTENDED_LOCALE_MODEL    1
82b174
+# include <string/strcasecmp.c>
82b174
+#endif
82b174
diff --git a/sysdeps/x86_64/strncase-nonascii.c b/sysdeps/x86_64/strncase-nonascii.c
82b174
new file mode 100644
82b174
index 0000000000000000..4db45017c189b87a
82b174
--- /dev/null
82b174
+++ b/sysdeps/x86_64/strncase-nonascii.c
82b174
@@ -0,0 +1,7 @@
82b174
+#include <string.h>
82b174
+
82b174
+extern int __strncasecmp_nonascii (const char *__s1, const char *__s2,
82b174
+                                   size_t __n);
82b174
+
82b174
+#define __strncasecmp __strncasecmp_nonascii
82b174
+#include <string/strncase.c>