While testing a GNU sed snapshot on macOS 10.13, I see this test failure: FAIL: testsuite/bug32082 ========================
valgrind report for 'posix' test: ================================== --85029-- run: /usr/bin/dsymutil "/Users/haible/devel/sed-4.8.39-23ea/build-64/./sed/sed" --85029-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option --85029-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 2 times) --85029-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 4 times) --85029-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 8 times) ==85029== Invalid read of size 16 ==85029== at 0x100EE6A05: _platform_memchr$VARIANT$Base (in /usr/lib/system/libsystem_platform.dylib) ==85029== by 0x100B7B0BD: getdelim (in /usr/lib/system/libsystem_c.dylib) ==85029== by 0x10000B0BE: ck_getdelim (utils.c:254) ==85029== by 0x1000090A9: read_file_line (execute.c:388) ==85029== by 0x100008A12: read_pattern_space (execute.c:718) ==85029== by 0x1000066DA: process_files (execute.c:1682) ==85029== by 0x10000A5D9: main (sed.c:378) ==85029== Address 0x1019bf1a0 is 16 bytes before a block of size 65,536 alloc'd ==85029== at 0x1000E7545: malloc (vg_replace_malloc.c:302) ==85029== by 0x100B7B500: __smakebuf (in /usr/lib/system/libsystem_c.dylib) ==85029== by 0x100B7EC75: __srefill0 (in /usr/lib/system/libsystem_c.dylib) ==85029== by 0x100B7ED65: __srefill (in /usr/lib/system/libsystem_c.dylib) ==85029== by 0x100B7B136: getdelim (in /usr/lib/system/libsystem_c.dylib) ==85029== by 0x10000B0BE: ck_getdelim (utils.c:254) ==85029== by 0x1000090A9: read_file_line (execute.c:388) ==85029== by 0x100008A12: read_pattern_space (execute.c:718) ==85029== by 0x1000066DA: process_files (execute.c:1682) ==85029== by 0x10000A5D9: main (sed.c:378) ==85029== ... FAIL testsuite/bug32082.sh (exit status: 1) An out-of-bounds read. Oh oh. When I reconfigure and recompile with the environment variable gl_cv_func_working_getdelim=no this test succeeds. Assuming that the GNU sed code is correct (it's not a particularly complex code), this proves that the out-of-bounds read comes from the macOS getdelim() function. This patch adds a workaround. TODO: Someone should test the same thing on the *BSD systems as well. 2022-10-16 Bruno Haible <br...@clisp.org> getdelim: Work around buggy implementation on macOS 10.13. * doc/posix-functions/getdelim.texi: Mention the macOS bug. * m4/getdelim.m4 (gl_FUNC_GETDELIM): Let the "checking for working getdelim function" test answer 'no' on macOS. diff --git a/doc/posix-functions/getdelim.texi b/doc/posix-functions/getdelim.texi index b076658574..7e1851fac3 100644 --- a/doc/posix-functions/getdelim.texi +++ b/doc/posix-functions/getdelim.texi @@ -12,6 +12,9 @@ Portability problems fixed by Gnulib: This function is missing on some platforms: Mac OS X 10.5, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 10, mingw, MSVC 14, Android 4.2. @item +This function makes out-of-bounds reads on some platforms: +macOS 10.13. +@item This function crashes when passed a pointer to a NULL buffer together with a pointer to a non-zero buffer size on some platforms: FreeBSD 8.0. diff --git a/m4/getdelim.m4 b/m4/getdelim.m4 index 0b63b55351..703c1f876f 100644 --- a/m4/getdelim.m4 +++ b/m4/getdelim.m4 @@ -1,4 +1,4 @@ -# getdelim.m4 serial 15 +# getdelim.m4 serial 16 dnl Copyright (C) 2005-2007, 2009-2022 Free Software Foundation, Inc. dnl @@ -11,7 +11,7 @@ AC_PREREQ([2.59]) AC_DEFUN([gl_FUNC_GETDELIM], [ AC_REQUIRE([gl_STDIO_H_DEFAULTS]) - AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_REQUIRE([AC_CANONICAL_HOST]) dnl Persuade glibc <stdio.h> to declare getdelim(). AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) @@ -24,8 +24,18 @@ AC_DEFUN([gl_FUNC_GETDELIM], dnl Found it in some library. Verify that it works. AC_CACHE_CHECK([for working getdelim function], [gl_cv_func_working_getdelim], - [echo fooNbarN | tr -d '\012' | tr N '\012' > conftest.data - AC_RUN_IFELSE([AC_LANG_SOURCE([[ + [case "$host_os" in + darwin*) + dnl On macOS 10.13, valgrind detected an out-of-bounds read during + dnl the GNU sed test suite: + dnl Invalid read of size 16 + dnl at 0x100EE6A05: _platform_memchr$VARIANT$Base (in /usr/lib/system/libsystem_platform.dylib) + dnl by 0x100B7B0BD: getdelim (in /usr/lib/system/libsystem_c.dylib) + dnl by 0x10000B0BE: ck_getdelim (utils.c:254) + gl_cv_func_working_getdelim=no ;; + *) + echo fooNbarN | tr -d '\012' | tr N '\012' > conftest.data + AC_RUN_IFELSE([AC_LANG_SOURCE([[ # include <stdio.h> # include <stdlib.h> # include <string.h> @@ -57,26 +67,28 @@ AC_DEFUN([gl_FUNC_GETDELIM], return 0; } ]])], - [gl_cv_func_working_getdelim=yes], - [gl_cv_func_working_getdelim=no], - [dnl We're cross compiling. - dnl Guess it works on glibc2 systems and musl systems. - AC_EGREP_CPP([Lucky GNU user], - [ + [gl_cv_func_working_getdelim=yes], + [gl_cv_func_working_getdelim=no], + [dnl We're cross compiling. + dnl Guess it works on glibc2 systems and musl systems. + AC_EGREP_CPP([Lucky GNU user], + [ #include <features.h> #ifdef __GNU_LIBRARY__ #if (__GLIBC__ >= 2) && !defined __UCLIBC__ Lucky GNU user #endif #endif - ], - [gl_cv_func_working_getdelim="guessing yes"], - [case "$host_os" in - *-musl*) gl_cv_func_working_getdelim="guessing yes" ;; - *) gl_cv_func_working_getdelim="$gl_cross_guess_normal" ;; - esac - ]) - ]) + ], + [gl_cv_func_working_getdelim="guessing yes"], + [case "$host_os" in + *-musl*) gl_cv_func_working_getdelim="guessing yes" ;; + *) gl_cv_func_working_getdelim="$gl_cross_guess_normal" ;; + esac + ]) + ]) + ;; + esac ]) case "$gl_cv_func_working_getdelim" in *yes) ;;