Fix BZ #14602: strstr and strcasestr return wrong result.
authorMaxim Kuvyrkov <maxim@codesourcery.com>
Tue, 9 Oct 2012 03:52:53 +0000 (20:52 -0700)
committerMaxim Kuvyrkov <maxim@codesourcery.com>
Tue, 9 Oct 2012 03:52:53 +0000 (20:52 -0700)
ChangeLog
string/str-two-way.h
string/strcasestr.c
string/strstr.c

index c4f561d..6af01e5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2012-10-08  Maxim Kuvyrkov  <maxim@codesourcery.com>
+
+       [BZ #14602]
+       * string/str-two-way.h (AVAILABLE1, AVAILABLE2, AVAILABLE1_USES_J):
+       Replace with ...
+       (CHECK_EOL): New macro.
+       (two_way_short_needle): Check beginning of haystack for EOL.  Use
+       CHECK_EOL.
+       * string/strcasestr.c (AVAILABLE1, AVAILABLE2, AVAILABLE1_USES_J):
+       Replace with CHECK_EOL.
+       * string/strstr.c (AVAILABLE1, AVAILABLE2, AVAILABLE1_USES_J):
+       Replace with CHECK_EOL.
+
 2012-10-08  Joseph Myers  <joseph@codesourcery.com>
 
        * math/gen-libm-test.pl (parse_args): Handle isinf and isnan as
index 59609b8..d2572da 100644 (file)
 # define CMP_FUNC memcmp
 #endif
 
-#ifndef AVAILABLE1
-# define AVAILABLE1(h, h_l, j, n_l) AVAILABLE (h, h_l, j, n_l)
-#endif
-#ifndef AVAILABLE2
-# define AVAILABLE2(h, h_l, j, n_l) (1)
+/* Check for end-of-line in strstr and strcasestr routines.
+   We piggy-back matching procedure for detecting EOL where possible,
+   and use AVAILABLE macro otherwise.  */
+#ifndef CHECK_EOL
+# define CHECK_EOL (0)
 #endif
+
+/* Return NULL if argument is '\0'.  */
 #ifndef RET0_IF_0
 # define RET0_IF_0(a) /* nothing */
 #endif
-#ifndef AVAILABLE1_USES_J
-# define AVAILABLE1_USES_J (1)
-#endif
 
 /* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN.
    Return the index of the first byte in the right half, and set
@@ -283,11 +282,23 @@ two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
         and use an optimized first-character loop.  */
       unsigned char needle_suffix = CANON_ELEMENT (needle[suffix]);
 
+#if CHECK_EOL
+      /* We start matching from the SUFFIX'th element, so make sure we
+        don't hit '\0' before that.  */
+      if (haystack_len < suffix + 1
+         && !AVAILABLE (haystack, haystack_len, 0, suffix + 1))
+       return NULL;
+#endif
+
       /* The two halves of needle are distinct; no extra memory is
         required, and any mismatch results in a maximal shift.  */
       period = MAX (suffix, needle_len - suffix) + 1;
       j = 0;
-      while (AVAILABLE1 (haystack, haystack_len, j, needle_len))
+      while (1
+#if !CHECK_EOL
+            && AVAILABLE (haystack, haystack_len, j, needle_len)
+#endif
+            )
        {
          unsigned char haystack_char;
          const unsigned char *pneedle;
@@ -298,13 +309,13 @@ two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
              != (haystack_char = CANON_ELEMENT (*phaystack++)))
            {
              RET0_IF_0 (haystack_char);
-#if AVAILABLE1_USES_J
+#if CHECK_EOL
              ++j;
 #endif
              continue;
            }
 
-#if !AVAILABLE1_USES_J
+#if !CHECK_EOL
          /* Calculate J if it wasn't kept up-to-date in the first-character
             loop.  */
          j = phaystack - &haystack[suffix] - 1;
@@ -346,8 +357,10 @@ two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
          else
            j += i - suffix + 1;
 
-         if (!AVAILABLE2 (haystack, haystack_len, j, needle_len))
+#if CHECK_EOL
+         if (!AVAILABLE (haystack, haystack_len, j, needle_len))
            break;
+#endif
 
          phaystack = &haystack[suffix + j];
        }
index 9467b7a..6aaf45f 100644 (file)
 #define AVAILABLE(h, h_l, j, n_l)                      \
   (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l))    \
    && ((h_l) = (j) + (n_l)))
-#define AVAILABLE1(h, h_l, j, n_l) (true)
-#define AVAILABLE2(h, h_l, j, n_l) AVAILABLE (h, h_l, j, n_l)
+#define CHECK_EOL (1)
 #define RET0_IF_0(a) if (!a) goto ret0
-#define AVAILABLE1_USES_J (0)
 #define CANON_ELEMENT(c) TOLOWER (c)
 #define CMP_FUNC(p1, p2, l)                            \
   __strncasecmp ((const char *) (p1), (const char *) (p2), l)
index cfed771..d74cb46 100644 (file)
 #define AVAILABLE(h, h_l, j, n_l)                      \
   (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l))    \
    && ((h_l) = (j) + (n_l)))
-#define AVAILABLE1(h, h_l, j, n_l) (true)
-#define AVAILABLE2(h, h_l, j, n_l) AVAILABLE (h, h_l, j, n_l)
+#define CHECK_EOL (1)
 #define RET0_IF_0(a) if (!a) goto ret0
-#define AVAILABLE1_USES_J (0)
 #include "str-two-way.h"
 
 #undef strstr