aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Kuvyrkov <maxim@codesourcery.com>2012-10-08 20:52:53 -0700
committerMaxim Kuvyrkov <maxim@codesourcery.com>2012-10-08 20:52:53 -0700
commit57e605ba50a42e1e5adc0f020f3752e80f117c10 (patch)
treeb21fda0d2a3ac232fa4d7896fd43a876a1e6520f
parentef1bb3618c77f92a5ab1a98f907e5bb5149dc3dc (diff)
downloadglibc-57e605ba50a42e1e5adc0f020f3752e80f117c10.zip
glibc-57e605ba50a42e1e5adc0f020f3752e80f117c10.tar.gz
glibc-57e605ba50a42e1e5adc0f020f3752e80f117c10.tar.bz2
Fix BZ #14602: strstr and strcasestr return wrong result.
-rw-r--r--ChangeLog13
-rw-r--r--string/str-two-way.h37
-rw-r--r--string/strcasestr.c4
-rw-r--r--string/strstr.c4
4 files changed, 40 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index c4f561d..6af01e5 100644
--- 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
diff --git a/string/str-two-way.h b/string/str-two-way.h
index 59609b8..d2572da 100644
--- a/string/str-two-way.h
+++ b/string/str-two-way.h
@@ -75,18 +75,17 @@
# 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];
}
diff --git a/string/strcasestr.c b/string/strcasestr.c
index 9467b7a..6aaf45f 100644
--- a/string/strcasestr.c
+++ b/string/strcasestr.c
@@ -43,10 +43,8 @@
#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)
diff --git a/string/strstr.c b/string/strstr.c
index cfed771..d74cb46 100644
--- a/string/strstr.c
+++ b/string/strstr.c
@@ -35,10 +35,8 @@
#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