From b224637928e9fc04e3cef3e10d02ccf042d01584 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Thu, 15 Dec 2016 18:27:10 +0000 Subject: Fix powerpc64/power7 memchr for large input sizes Current optimized powercp64/power7 memchr uses a strategy to check for p versus align(p+n) (where 'p' is the input char pointer and n the maximum size to check for the byte) without taking care for possible overflow on the pointer addition in case of large 'n'. It was triggered by 3038145ca23 where default rawmemchr (used to created ppc64 rawmemchr in ifunc selection) now uses memchr (p, c, (size_t)-1) on its implementation. This patch fixes it by implement a satured addition where overflows sets the maximum pointer size to UINTPTR_MAX. Checked on powerpc64le-linux-gnu. [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. --- string/test-memchr.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'string/test-memchr.c') diff --git a/string/test-memchr.c b/string/test-memchr.c index 449a19a..e7ba02b 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 (); -- cgit v1.1