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