diff mbox

[v2] Fix powerpc64/power7 memchr for large input sizes

Message ID 1481829263-3740-1-git-send-email-adhemerval.zanella@linaro.org
State New
Headers show

Commit Message

Adhemerval Zanella Netto Dec. 15, 2016, 7:14 p.m. UTC
Changes from previous version:

  - Add test-memchr.c SIZE_MAX tests.

--

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                                 |  9 ++++++++
 string/test-memchr.c                      | 38 +++++++++++++++++++++++--------
 sysdeps/powerpc/powerpc64/power7/memchr.S | 12 +++++++++-
 3 files changed, 49 insertions(+), 10 deletions(-)

Comments

Steven Munroe Dec. 15, 2016, 10:08 p.m. UTC | #1
On Thu, 2016-12-15 at 17:14 -0200, Adhemerval Zanella wrote:
> 
> +        make sure the bye is within the size range (that's why 

Typo on byte but otherwise LGTM
cseo Dec. 16, 2016, 3:46 p.m. UTC | #2
On 12/15/16, 5:14 PM, "Adhemerval Zanella" <libc-alpha-owner@sourceware.org on behalf of adhemerval.zanella@linaro.org> wrote:

    +      /* 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.  */

    

Typo on ‘byte’ and missing closing bracket.

LGTM after these fixes.
diff mbox

Patch

diff --git a/string/test-memchr.c b/string/test-memchr.c
index 449a19a..7431386 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, 32, SIZE_MAX, 23);
+	  do_test (i, 16 - j, 32, 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 03f0d7c..0737100 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