]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix powerpc64/power7 memchr for large input sizes
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Thu, 15 Dec 2016 18:27:10 +0000 (18:27 +0000)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 16 Dec 2016 13:30:20 +0000 (11:30 -0200)
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.

ChangeLog
string/test-memchr.c
sysdeps/powerpc/powerpc64/power7/memchr.S

index 374a69f8db9c7d6c0aab182435b9f3828fd62098..628540538b102317ddb523c4cc0e9d737ec70e23 100644 (file)
--- 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.
index 449a19ae594c2fec1d59b078104d576cf88d0b93..e7ba02b617eac391b3f9155d6022eea0adf663a3 100644 (file)
@@ -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 ();
index 03f0d7c2dd0e5fbc69ec69853d88e7603acd33d0..0737100fd5a84eb182f667690483484431388db0 100644 (file)
@@ -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