Fix glibc 2.7 strtok_r() bug in a more permanent fashion.
authorBen Pfaff <blp@nicira.com>
Wed, 10 Jun 2009 21:16:40 +0000 (14:16 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 10 Jun 2009 22:31:20 +0000 (15:31 -0700)
The glibc 2.7 headers contain a bug that causes strtok_r() to segfault
in some circumstances.  Until now, we have been working around this
problem at each invocation, but this depends on the programmer to remember
to do so each time.

This commit instead adds a shim that adds a work-around to the string.h
header itself, so that it is much more difficult to miss the workaround.

acinclude.m4
configure.ac
lib/vconn-ssl.c
lib/vconn-tcp.c
secchan/netflow.c
utilities/ovs-dpctl.c
utilities/ovs-ofctl.c

index f16bbf4bc68455865315acf297315d4f5933edac..1e7989f0196cc0707be9421b12f5f8330281a42c 100644 (file)
@@ -154,6 +154,37 @@ AC_DEFUN([OVS_CHECK_IF_PACKET],
                 [Define to 1 if net/if_packet.h is available.])
    fi])
 
+dnl Checks for buggy strtok_r.
+dnl
+dnl Some versions of glibc 2.7 has a bug in strtok_r when compiling
+dnl with optimization that can cause segfaults:
+dnl
+dnl http://sources.redhat.com/bugzilla/show_bug.cgi?id=5614.
+AC_DEFUN([OVS_CHECK_STRTOK_R],
+  [AC_CACHE_CHECK(
+     [whether strtok_r macro segfaults on some inputs],
+     [ovs_cv_strtok_r_bug],
+     [AC_RUN_IFELSE(
+        [AC_LANG_PROGRAM([#include <stdio.h>
+                          #include <string.h>
+                         ],
+                         [[char string[] = ":::";
+                           char *save_ptr = (char *) 0xc0ffee;
+                           char *token1, *token2;
+                           token1 = strtok_r(string, ":", &save_ptr);
+                           token2 = strtok_r(NULL, ":", &save_ptr);
+                           printf ("%s %s\n", token1, token2);
+                           return 0;
+                          ]])],
+        [ovs_cv_strtok_r_bug=no],
+        [ovs_cv_strtok_r_bug=yes],
+        [ovs_cv_strtok_r_bug=yes])])
+   if test $ovs_cv_strtok_r_bug = yes; then
+     AC_DEFINE([HAVE_STRTOK_R_BUG], [1],
+               [Define if strtok_r macro segfaults on some inputs])
+   fi
+])
+
 dnl ----------------------------------------------------------------------
 dnl These macros are from GNU PSPP, with the following original license:
 dnl Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
index 65152d17bc632a83f4b181e1f0b36ee8418b67fa..0cc535c63ca3825a01b2e44e55b40596e4cbffa2 100644 (file)
@@ -46,6 +46,7 @@ OVS_CHECK_CURSES
 OVS_CHECK_LINUX_VT_H
 OVS_CHECK_PCRE
 OVS_CHECK_IF_PACKET
+OVS_CHECK_STRTOK_R
 
 if $build_userspace; then
     OVS_CHECK_PKIDIR
index 20bfb9793273c3f7eccc6ba61ed90ceece5a11f7..96890e6b3006bf708feb4bdfbbf2da7fb3b2444f 100644 (file)
@@ -279,12 +279,8 @@ ssl_open(const char *name, char *suffix, struct vconn **vconnp)
         return retval;
     }
 
-    /* Glibc 2.7 has a bug in strtok_r when compiling with optimization that
-     * can cause segfaults here:
-     * http://sources.redhat.com/bugzilla/show_bug.cgi?id=5614.
-     * Using "::" instead of the obvious ":" works around it. */
-    host_name = strtok_r(suffix, "::", &save_ptr);
-    port_string = strtok_r(NULL, "::", &save_ptr);
+    host_name = strtok_r(suffix, ":", &save_ptr);
+    port_string = strtok_r(NULL, ":", &save_ptr);
     if (!host_name) {
         ovs_error(0, "%s: bad peer name format", name);
         return EAFNOSUPPORT;
index 081ac26ded9e2f0805ff94435425ec73f03be1cf..3b29a290c7febf38e320550a8c383e9c3747f161 100644 (file)
@@ -64,12 +64,8 @@ tcp_open(const char *name, char *suffix, struct vconn **vconnp)
     int retval;
     int fd;
 
-    /* Glibc 2.7 has a bug in strtok_r when compiling with optimization that
-     * can cause segfaults here:
-     * http://sources.redhat.com/bugzilla/show_bug.cgi?id=5614.
-     * Using "::" instead of the obvious ":" works around it. */
-    host_name = strtok_r(suffix, "::", &save_ptr);
-    port_string = strtok_r(NULL, "::", &save_ptr);
+    host_name = strtok_r(suffix, ":", &save_ptr);
+    port_string = strtok_r(NULL, ":", &save_ptr);
     if (!host_name) {
         ovs_error(0, "%s: bad peer name format", name);
         return EAFNOSUPPORT;
index 99f3eea4aa2b7e2b61dc95aea4d637ca742375de..5d90eea3c622dd541fe51cfb1ce784c7001cbdfa 100644 (file)
@@ -118,8 +118,8 @@ open_collector(char *dst)
      * can cause segfaults here:
      * http://sources.redhat.com/bugzilla/show_bug.cgi?id=5614.
      * Using "::" instead of the obvious ":" works around it. */
-    host_name = strtok_r(dst, "::", &save_ptr);
-    port_string = strtok_r(NULL, "::", &save_ptr);
+    host_name = strtok_r(dst, ":", &save_ptr);
+    port_string = strtok_r(NULL, ":", &save_ptr);
     if (!host_name) {
         ovs_error(0, "%s: bad peer name format", dst);
         return -EAFNOSUPPORT;
index ccddd2f2981643e758eea95fcf94a6ccea8ff132..381c936f80635aa457ced9f883fb619cc268055b 100644 (file)
@@ -281,7 +281,7 @@ do_add_if(int argc UNUSED, char *argv[])
         int flags = 0;
         int error;
 
-        devname = strtok_r(argv[i], ",,", &save_ptr);
+        devname = strtok_r(argv[i], ",", &save_ptr);
         if (!devname) {
             ovs_error(0, "%s is not a valid network device name", argv[i]);
             continue;
index 8b343956d431d5ac75b84a368431bb15abc311e6..051a88aafc013e2516aac4f95bd8e5ae92a6bd8b 100644 (file)
@@ -457,14 +457,14 @@ str_to_ip(const char *str_, uint32_t *ip)
     struct in_addr in_addr;
     int n_wild, retval;
 
-    name = strtok_r(str, "//", &save_ptr);
+    name = strtok_r(str, "/", &save_ptr);
     retval = name ? lookup_ip(name, &in_addr) : EINVAL;
     if (retval) {
         ovs_fatal(0, "%s: could not convert to IP address", str);
     }
     *ip = in_addr.s_addr;
 
-    netmask = strtok_r(NULL, "//", &save_ptr);
+    netmask = strtok_r(NULL, "/", &save_ptr);
     if (netmask) {
         uint8_t o[4];
         if (sscanf(netmask, "%"SCNu8".%"SCNu8".%"SCNu8".%"SCNu8,