memchr.m4 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. # memchr.m4 serial 18
  2. dnl Copyright (C) 2002-2004, 2009-2023 Free Software Foundation, Inc.
  3. dnl This file is free software; the Free Software Foundation
  4. dnl gives unlimited permission to copy and/or distribute it,
  5. dnl with or without modifications, as long as this notice is preserved.
  6. AC_DEFUN_ONCE([gl_FUNC_MEMCHR],
  7. [
  8. AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
  9. dnl Check for prerequisites for memory fence checks.
  10. gl_FUNC_MMAP_ANON
  11. AC_CHECK_HEADERS_ONCE([sys/mman.h])
  12. AC_CHECK_FUNCS_ONCE([mprotect])
  13. AC_REQUIRE([gl_STRING_H_DEFAULTS])
  14. # Detect platform-specific bugs in some versions of glibc:
  15. # memchr should not dereference anything with length 0
  16. # https://bugzilla.redhat.com/show_bug.cgi?id=499689
  17. # memchr should not dereference overestimated length after a match
  18. # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=521737
  19. # https://sourceware.org/bugzilla/show_bug.cgi?id=10162
  20. # memchr should cast the second argument to 'unsigned char'.
  21. # This bug exists in Android 4.3.
  22. # Assume that memchr works on platforms that lack mprotect.
  23. AC_CACHE_CHECK([whether memchr works], [gl_cv_func_memchr_works],
  24. [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
  25. #include <string.h>
  26. #if HAVE_SYS_MMAN_H
  27. # include <fcntl.h>
  28. # include <unistd.h>
  29. # include <sys/types.h>
  30. # include <sys/mman.h>
  31. # ifndef MAP_FILE
  32. # define MAP_FILE 0
  33. # endif
  34. #endif
  35. ]], [[
  36. int result = 0;
  37. char *fence = NULL;
  38. #if HAVE_SYS_MMAN_H && HAVE_MPROTECT
  39. # if HAVE_MAP_ANONYMOUS
  40. const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
  41. const int fd = -1;
  42. # else /* !HAVE_MAP_ANONYMOUS */
  43. const int flags = MAP_FILE | MAP_PRIVATE;
  44. int fd = open ("/dev/zero", O_RDONLY, 0666);
  45. if (fd >= 0)
  46. # endif
  47. {
  48. int pagesize = getpagesize ();
  49. char *two_pages =
  50. (char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE,
  51. flags, fd, 0);
  52. if (two_pages != (char *)(-1)
  53. && mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0)
  54. fence = two_pages + pagesize;
  55. }
  56. #endif
  57. if (fence)
  58. {
  59. /* Test against bugs on glibc systems. */
  60. if (memchr (fence, 0, 0))
  61. result |= 1;
  62. strcpy (fence - 9, "12345678");
  63. if (memchr (fence - 9, 0, 79) != fence - 1)
  64. result |= 2;
  65. if (memchr (fence - 1, 0, 3) != fence - 1)
  66. result |= 4;
  67. /* Test against bug on AIX 7.2. */
  68. if (memchr (fence - 4, '6', 16) != fence - 4)
  69. result |= 8;
  70. }
  71. /* Test against bug on Android 4.3. */
  72. {
  73. char input[3];
  74. input[0] = 'a';
  75. input[1] = 'b';
  76. input[2] = 'c';
  77. if (memchr (input, 0x789abc00 | 'b', 3) != input + 1)
  78. result |= 16;
  79. }
  80. return result;
  81. ]])],
  82. [gl_cv_func_memchr_works=yes],
  83. [gl_cv_func_memchr_works=no],
  84. [case "$host_os" in
  85. # Guess no on Android.
  86. linux*-android*) gl_cv_func_memchr_works="guessing no" ;;
  87. # Guess yes on native Windows.
  88. mingw*) gl_cv_func_memchr_works="guessing yes" ;;
  89. # If we don't know, obey --enable-cross-guesses.
  90. *) gl_cv_func_memchr_works="$gl_cross_guess_normal" ;;
  91. esac
  92. ])
  93. ])
  94. case "$gl_cv_func_memchr_works" in
  95. *yes) ;;
  96. *) REPLACE_MEMCHR=1 ;;
  97. esac
  98. ])
  99. # Prerequisites of lib/memchr.c.
  100. AC_DEFUN([gl_PREREQ_MEMCHR], [
  101. AC_CHECK_HEADERS([bp-sym.h])
  102. ])