From 7afb30e15c8ea61e9dde2326551807791f3a7cea Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Tue, 29 Sep 2020 19:34:59 +0200 Subject: [PATCH] libast: Work around gcc optimiser bug for strdup() (rhbz#1221766) Red Hat erratum: https://bugzilla.redhat.com/1221766 "Previously, the gcc utility optimized out a non-NULL test in the ksh implementation of the strdup() function. This caused an unexpected termination when ksh was executed in a clean chroot environment. With this update, ksh compilation parameters have been updated to prevent optimizing out a non-NULL test, and ksh no longer crashes in clean chroot environments." The optimizer bug occurs in that function's single-line body: return (s && (t = oldof(0, char, n = strlen(s) + 1, 0))) ? (char*)memcpy(t, s, n) : (char*)0; So it must be the test for non-NULL 's' that fails. And 's' is declared in the function definition, as follows: extern char* strdup(register const char* s) So that makes me wonder if we can work around the bug by simply removing the 'const' (and the 'register' while we're at it). However, I have no easy way to verify that at the moment. The Red Hat patch instead tells gcc to disable optimization for this function using a #pragma directive. I have no idea if that gcc optimiser bug has been fixed in the meantime, but experience from c258a04f has shown that we cannot trust that it has been fixed (that other optimizer bug is at least a decade old and still not fixed). So, in it goes, until someone shows evidence that we no longer need it. Original patch: https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-badgcc.patch src/lib/libast/string/strdup.c: - Tell GCC to disable all optimisations for strdup(). --- src/lib/libast/string/strdup.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib/libast/string/strdup.c b/src/lib/libast/string/strdup.c index 56798736a..e2a8be5b6 100644 --- a/src/lib/libast/string/strdup.c +++ b/src/lib/libast/string/strdup.c @@ -50,6 +50,13 @@ __STDPP__directive pragma pp:nohide strdup #define extern __EXPORT__ #endif +/* + * Work around a null-test optimization bug in GCC. + * https://bugzilla.redhat.com/1221766 + */ +#pragma GCC push_options +#pragma GCC optimize ("O0") + extern char* strdup(register const char* s) { @@ -58,3 +65,5 @@ strdup(register const char* s) return (s && (t = oldof(0, char, n = strlen(s) + 1, 0))) ? (char*)memcpy(t, s, n) : (char*)0; } + +#pragma GCC pop_options