On 6/30/24 13:14, Po Lu wrote:
I think there should be a trivial test for a functional strnlen in
strnlen.m4, since it would be terrible to duplicate what ought to be the
responsibility of Gnulib in Emacs's configure.ac.

Here's a first cut at doing that, as a patch to Emacs master that I have not installed. Could you please give it a try? If it works I can migrate it into Gnulib and Autoconf.

The new code in strnlen.m4 isn't quite the same as the Emacs configure.ac code it replaces, but I hope it's good enough. I should be more portable as it doesn't depend on Emacs configure.ac vars.
From 2e8c14206b1a8e3f8bcf34639b3d65861741bd64 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 12 Jul 2024 17:23:30 +0100
Subject: [PATCH] Improve strnlen bug detection

The workaround for the Android 5.0 (API 21) strnlen bug
is now done in a different way in m4/strnlen.m4, with the idea of
migrating that into Gnulib and then to Autoconf.
* configure.ac (ORIGINAL_AC_FUNC_STRNLEN, AC_FUNC_STRNLEN):
Remove.
* m4/strnlen.m4 (AC_FUNC_STRNLEN): Replace if Autoconf 2.72 or
earlier, with code that detects the Android problem with strnlen.
This version works around some further bugs in the test, notably,
misplaced 'volatile' and need for volatile in the AIX 4.3 bug
check too.
---
 configure.ac  | 24 ------------------------
 m4/strnlen.m4 | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/configure.ac b/configure.ac
index 54c46151bd5..b53224e764d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1611,30 +1611,6 @@ AC_DEFUN
   [HAVE_OFF64_T=1
    AC_SUBST([HAVE_OFF64_T])])
 
-# `strnlen' cannot accept nlen greater than the size of the object S
-# on Android 5.0 and earlier.
-m4_define([ORIGINAL_AC_FUNC_STRNLEN], m4_defn([AC_FUNC_STRNLEN]))
-AC_DEFUN([AC_FUNC_STRNLEN], [
-AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])dnl
-AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_CACHE_CHECK([for strnlen capable of accepting large limits],
-  [emacs_cv_func_strnlen_working],
-  [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], [[
-  volatile size_t (*strnlen_pointer) (const char *s, size_t) = &strnlen;
-  if ((*strnlen_pointer) ("", -1) != 0)
-    return 1;
-  return 0;
-]])],[emacs_cv_func_strnlen_working=yes],
-     [emacs_cv_func_strnlen_working=no],
-     [# Guess no on Android 21 and earlier, yes elsewhere.
-      AS_IF([test -n "$ANDROID_SDK" && test "$ANDROID_SDK" -lt 22],
-        [emacs_cv_func_strnlen_working=no],
-	[emacs_cv_func_strnlen_working='guessing yes'])])])
-AS_IF([test "$emacs_cv_func_strnlen_working" != "no"],
-  [ORIGINAL_AC_FUNC_STRNLEN],
-  [ac_cv_func_strnlen_working=no
-   AC_LIBOBJ([strnlen])])])
-
 # Initialize gnulib right after choosing the compiler.
 dnl Amongst other things, this sets AR and ARFLAGS.
 gl_EARLY
diff --git a/m4/strnlen.m4 b/m4/strnlen.m4
index b4d2778524e..83a75c0c327 100644
--- a/m4/strnlen.m4
+++ b/m4/strnlen.m4
@@ -1,11 +1,60 @@
 # strnlen.m4
-# serial 14
+# serial 15
 dnl Copyright (C) 2002-2003, 2005-2007, 2009-2024 Free Software Foundation,
 dnl Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
+m4_version_prereq([2.73], [], [
+# Replace AC_FUNC_STRNLEN from Autoconf 2.72 and earlier,
+# which does not check for Android strnlen bugs.
+
+AC_DEFUN([AC_FUNC_STRNLEN],
+[AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])dnl
+AC_CACHE_CHECK([for working strnlen], [ac_cv_func_strnlen_working],
+[AC_RUN_IFELSE(
+   [AC_LANG_PROGRAM(
+      [AC_INCLUDES_DEFAULT
+       [/* Use pstrnlen to test; 'volatile' prevents the compiler
+           from optimizing the strnlen calls away.  */
+        size_t (*volatile pstrnlen) (char const *, size_t) = strnlen;
+        char const s[] = "foobar";
+        int s_len = sizeof s - 1;
+       ]],
+      [[
+        /* AIX 4.3 is buggy: strnlen (S, 1) == 3.  */
+        int i;
+        for (i = 0; i < s_len + 1; ++i)
+          {
+            int expected = i <= s_len ? i : s_len;
+            if (pstrnlen (s, i) != expected)
+              return 1;
+          }
+
+        /* Android 5.0 (API 21) strnlen ("", SIZE_MAX) incorrectly crashes.  */
+        if (pstrnlen ("", -1) != 0)
+          return 1;]])],
+   [ac_cv_func_strnlen_working=yes],
+   [ac_cv_func_strnlen_working=no],
+   [AC_COMPILE_IFELSE(
+      [AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
+         [[#if defined _AIX && !defined _AIX51
+            #error "AIX pre 5.1 is buggy"
+           #endif
+           #ifdef __ANDROID__
+            #include <android/api-level.h>
+            #if __ANDROID_API__ < 22
+             #error "Android API < 22 is buggy"
+            #endif
+           #endif
+         ]])],
+      [ac_cv_func_strnlen_working=yes],
+      [ac_cv_func_strnlen_working=no])])])
+test $ac_cv_func_strnlen_working = no && AC_LIBOBJ([strnlen])
+])# AC_FUNC_STRNLEN
+])
+
 AC_DEFUN([gl_FUNC_STRNLEN],
 [
   AC_REQUIRE([gl_STRING_H_DEFAULTS])
-- 
2.45.2

Reply via email to