summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--string/test-memchr.c38
-rw-r--r--sysdeps/powerpc/powerpc64/power7/memchr.S12
3 files changed, 49 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 374a69f8db..628540538b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2016-12-16 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+ [BZ# 20971]
+ * sysdeps/powerpc/powerpc64/power7/memchr.S (__memchr): Avoid
+ overflow in pointer addition.
+ * string/test-memchr.c (do_test): Add an argument to pass as
+ the size on memchr.
+ (test_main): Add check for SIZE_MAX.
+
2016-12-16 Gabriel F. T. Gomes <gftg@linux.vnet.ibm.com>
* math/Makefile (gen-libm-calls): Remove w_scalblnF.
diff --git a/string/test-memchr.c b/string/test-memchr.c
index 449a19ae59..e7ba02b617 100644
--- a/string/test-memchr.c
+++ b/string/test-memchr.c
@@ -71,7 +71,7 @@ do_one_test (impl_t *impl, const CHAR *s, int c, size_t n, CHAR *exp_res)
}
static void
-do_test (size_t align, size_t pos, size_t len, int seek_char)
+do_test (size_t align, size_t pos, size_t len, size_t n, int seek_char)
{
size_t i;
CHAR *result;
@@ -103,7 +103,7 @@ do_test (size_t align, size_t pos, size_t len, int seek_char)
}
FOR_EACH_IMPL (impl, 0)
- do_one_test (impl, (CHAR *) (buf + align), seek_char, len, result);
+ do_one_test (impl, (CHAR *) (buf + align), seek_char, n, result);
}
static void
@@ -167,7 +167,7 @@ do_random_tests (void)
int
test_main (void)
{
- size_t i;
+ size_t i, j;
test_init ();
@@ -178,15 +178,35 @@ test_main (void)
for (i = 1; i < 8; ++i)
{
- do_test (0, 16 << i, 2048, 23);
- do_test (i, 64, 256, 23);
- do_test (0, 16 << i, 2048, 0);
- do_test (i, 64, 256, 0);
+ do_test (0, 16 << i, 2048, 2048, 23);
+ do_test (i, 64, 256, 256, 23);
+ do_test (0, 16 << i, 2048, 2048, 0);
+ do_test (i, 64, 256, 256, 0);
+
+ /* Check for large input sizes and for these cases we need to
+ make sure the bye is within the size range (that's why
+ 7 << i must be smaller than 2048. */
+ do_test (0, 7 << i, 2048, SIZE_MAX, 23);
+ do_test (0, 2048 - i, 2048, SIZE_MAX, 23);
+ do_test (i, 64, 256, SIZE_MAX, 23);
+ do_test (0, 7 << i, 2048, SIZE_MAX, 0);
+ do_test (0, 2048 - i, 2048, SIZE_MAX, 0);
+ do_test (i, 64, 256, SIZE_MAX, 0);
}
+
+ for (i = 1; i < 16; ++i)
+ {
+ for (j = 1; j < 16; j++)
+ {
+ do_test (0, 16 - j, 16, SIZE_MAX, 23);
+ do_test (i, 16 - j, 16, SIZE_MAX, 23);
+ }
+ }
+
for (i = 1; i < 32; ++i)
{
- do_test (0, i, i + 1, 23);
- do_test (0, i, i + 1, 0);
+ do_test (0, i, i + 1, i + 1, 23);
+ do_test (0, i, i + 1, i + 1, 0);
}
do_random_tests ();
diff --git a/sysdeps/powerpc/powerpc64/power7/memchr.S b/sysdeps/powerpc/powerpc64/power7/memchr.S
index 03f0d7c2dd..0737100fd5 100644
--- a/sysdeps/powerpc/powerpc64/power7/memchr.S
+++ b/sysdeps/powerpc/powerpc64/power7/memchr.S
@@ -26,7 +26,17 @@ ENTRY (__memchr)
dcbt 0,r3
clrrdi r8,r3,3
insrdi r4,r4,8,48
- add r7,r3,r5 /* Calculate the last acceptable address. */
+
+ /* Calculate the last acceptable address and check for possible
+ addition overflow by using satured math:
+ r7 = r3 + r5
+ r7 |= -(r7 < x) */
+ add r7,r3,r5
+ subfc r6,r3,r7
+ subfe r9,r9,r9
+ extsw r6,r9
+ or r7,r7,r6
+
insrdi r4,r4,16,32
cmpldi r5,32
li r9, -1