Patch to libiberty to test whether sunos4 strncmp is broken
Kaveh R. Ghazi
ghazi@caip.rutgers.edu
Thu Apr 27 08:21:00 GMT 2000
The following patch uses a testcase provided by Jim Wilson to test
whether strncmp reads past the end of its strings. If strncmp is
found to be broken, a byte-at-a-time replacement version is provided
in libiberty.a.
See: http://gcc.gnu.org/ml/gcc-bugs/2000-03/msg00475.html
I slightly modified the test so that it works with either gcc or cc
used to configure/build libiberty. I also tried to make sure
platforms without mmap won't superfluously replace strncmp due to link
failures.
Tested on SunOS4 (where strncmp is replaced) and x86-linux (where it
is not replaced.)
Okay to install?
--Kaveh
Wed Apr 26 18:01:24 2000 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* aclocal.m4: New file with new test libiberty_AC_FUNC_STRNCMP.
* configure.in (AC_CHECK_HEADERS): Add sys/mman.h fcntl.h.
(libiberty_AC_FUNC_STRNCMP): Invoke.
* strncmp.c: New file.
diff -rup orig/egcs-CVS20000426/libiberty/aclocal.m4 egcs-CVS20000426/libiberty/aclocal.m4
--- orig/egcs-CVS20000426/libiberty/aclocal.m4 Wed Apr 26 11:47:51 2000
+++ egcs-CVS20000426/libiberty/aclocal.m4 Wed Apr 26 11:41:55 2000
@@ -0,0 +1,70 @@
+dnl See whether strncmp reads past the end of its string parameters.
+dnl On some versions of SunOS4 at least, strncmp reads a word at a time
+dnl but erroneously reads past the end of strings. This can cause
+dnl a SEGV in some cases.
+AC_DEFUN(libiberty_AC_FUNC_STRNCMP,
+[AC_REQUIRE([AC_FUNC_MMAP])
+AC_CACHE_CHECK([for working strncmp],
+ ac_cv_func_strncmp_works,
+[AC_TRY_RUN(
+[#include <sys/types.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#ifndef MAP_ANON
+#ifdef MAP_ANONYMOUS
+#define MAP_ANON MAP_ANONYMOUS
+#else
+#define MAP_ANON MAP_FILE
+#endif
+#endif
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
+
+#define MAP_LEN 0x10000
+
+main ()
+{
+#if defined(HAVE_MMAP) || defined(HAVE_MMAP_ANYWHERE)
+ char *p;
+ int dev_zero;
+
+ dev_zero = open ("/dev/zero", O_RDONLY);
+ if (dev_zero < 0)
+ exit (1);
+
+ p = (char *) mmap (0, MAP_LEN, PROT_READ|PROT_WRITE,
+ MAP_ANON|MAP_PRIVATE, dev_zero, 0);
+ if (p == (char *)-1)
+ exit (2);
+ else
+ {
+ char *string = "__si_type_info";
+ char *q = (char *) p + MAP_LEN - strlen (string) - 2;
+ char *r = (char *) p + 0xe;
+
+ strcpy (q, string);
+ strcpy (r, string);
+ strncmp (r, q, 14);
+ }
+#endif /* HAVE_MMAP || HAVE_MMAP_ANYWHERE */
+ exit (0);
+}
+], ac_cv_func_strncmp_works=yes, ac_cv_func_strncmp_works=no,
+ ac_cv_func_strncmp_works=no)
+rm -f core core.* *.core])
+if test $ac_cv_func_strncmp_works = no ; then
+ LIBOBJS="$LIBOBJS strncmp.o"
+fi
+])
diff -rup orig/egcs-CVS20000426/libiberty/configure.in egcs-CVS20000426/libiberty/configure.in
--- orig/egcs-CVS20000426/libiberty/configure.in Tue Jan 4 10:59:04 2000
+++ egcs-CVS20000426/libiberty/configure.in Wed Apr 26 11:40:00 2000
@@ -109,7 +109,7 @@ AC_SUBST_FILE(host_makefile_frag)
# It's OK to check for header files. Although the compiler may not be
# able to link anything, it had better be able to at least compile
# something.
-AC_CHECK_HEADERS(sys/file.h sys/param.h stdlib.h string.h unistd.h strings.h sys/time.h sys/resource.h sys/stat.h)
+AC_CHECK_HEADERS(sys/file.h sys/param.h stdlib.h string.h unistd.h strings.h sys/time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h)
AC_HEADER_SYS_WAIT
# This is the list of functions which libiberty will provide if they
@@ -351,6 +351,8 @@ EOF
done
AC_CHECK_FUNCS($checkfuncs)
fi
+
+libiberty_AC_FUNC_STRNCMP
# Install a library built with a cross compiler in $(tooldir) rather
# than $(libdir).
diff -rup orig/egcs-CVS20000426/libiberty/strncmp.c egcs-CVS20000426/libiberty/strncmp.c
--- orig/egcs-CVS20000426/libiberty/strncmp.c Wed Apr 26 11:47:11 2000
+++ egcs-CVS20000426/libiberty/strncmp.c Wed Apr 26 11:46:18 2000
@@ -0,0 +1,28 @@
+/* strncmp -- compare two strings, stop after n bytes.
+ This function is in the public domain. */
+
+#include <ansidecl.h>
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+int
+strncmp(s1, s2, n)
+ const char *s1, *s2;
+ register size_t n;
+{
+ register unsigned char u1, u2;
+
+ while (n-- > 0)
+ {
+ u1 = (unsigned char) *s1++;
+ u2 = (unsigned char) *s2++;
+ if (u1 != u2)
+ return u1 - u2;
+ if (u1 == '\0')
+ return 0;
+ }
+ return 0;
+}
More information about the Gcc-patches
mailing list