]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix v9/64-bit strcmp when string ends in multiple zero bytes.
authorDavid S. Miller <davem@davemloft.net>
Wed, 30 Apr 2014 19:57:51 +0000 (12:57 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 1 May 2014 20:21:03 +0000 (16:21 -0400)
[BZ #16885]
* sysdeps/sparc/sparc64/strcmp.S: Fix end comparison handling when
multiple zero bytes exist at the end of a string.
Reported by Aurelien Jarno <aurelien@aurel32.net>

* string/test-strcmp.c (check): Add explicit test for situations where
there are multiple zero bytes after the first.

ChangeLog
string/test-strcmp.c
sysdeps/sparc/sparc64/strcmp.S

index fa1ebb4601557855c9798d5344e737492a52460a..38c96450f7a648c5abe1340a552304f5965bf6a8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2014-05-01  David S. Miller  <davem@davemloft.net>
+
+       [BZ #16885]
+       * sysdeps/sparc/sparc64/strcmp.S: Fix end comparison handling when
+       multiple zero bytes exist at the end of a string.
+       Reported by Aurelien Jarno <aurelien@aurel32.net>
+
+       * string/test-strcmp.c (check): Add explicit test for situations where
+       there are multiple zero bytes after the first.
+
 2014-01-29  H.J. Lu  <hongjiu.lu@intel.com>
 
        [BZ #16510]
index 000c51091c6c22678c80023aa60afb110dd41f37..0fb41316b4b0fd9c549f2422342f098d5876fffd 100644 (file)
@@ -348,6 +348,34 @@ check (void)
                FOR_EACH_IMPL (impl, 0)
                check_result (impl, s1 + i1, s2 + i2, exp_result);
       }
+
+  /* Test cases where there are multiple zero bytes after the first.  */
+
+  for (size_t i = 0; i < 16 + 1; i++)
+    {
+      s1[i] = 0x00;
+      s2[i] = 0x00;
+    }
+
+  for (size_t i = 0; i < 16; i++)
+    {
+      int exp_result;
+
+      for (int val = 0x01; val < 0x100; val++)
+       {
+         for (size_t j = 0; j < i; j++)
+           {
+             s1[j] = val;
+             s2[j] = val;
+           }
+
+         s2[i] = val;
+
+         exp_result = SIMPLE_STRCMP (s1, s2);
+         FOR_EACH_IMPL (impl, 0)
+           check_result (impl, s1, s2, exp_result);
+       }
+    }
 }
 
 
index 386e0abc60e6d24151d631630acd4931d09940ed..4abf86f297d2279825c1c9317394d333f6894e0f 100644 (file)
@@ -121,6 +121,37 @@ ENTRY(strcmp)
        movleu  %xcc, -1, %o0
        srlx    rTMP1, 7, rTMP1
 
+       /* In order not to be influenced by bytes after the zero byte, we
+        * have to retain only the highest bit in the mask for the comparison
+        * with rSTRXOR to work properly.
+        */
+       mov     0, rTMP2
+       andcc   rTMP1, 0x0100, %g0
+
+       movne   %xcc, 8, rTMP2
+       sllx    rTMP1, 63 - 16, %o1
+
+       movrlz  %o1, 16, rTMP2
+       sllx    rTMP1, 63 - 24, %o1
+
+       movrlz  %o1, 24, rTMP2
+       sllx    rTMP1, 63 - 32, %o1
+
+       movrlz  %o1, 32, rTMP2
+       sllx    rTMP1, 63 - 40, %o1
+
+       movrlz  %o1, 40, rTMP2
+       sllx    rTMP1, 63 - 48, %o1
+
+       movrlz  %o1, 48, rTMP2
+       sllx    rTMP1, 63 - 56, %o1
+
+       movrlz  %o1, 56, rTMP2
+
+       srlx    rTMP1, rTMP2, rTMP1
+
+       sllx    rTMP1, rTMP2, rTMP1
+
        cmp     rTMP1, rSTRXOR
        retl
         movgu  %xcc, 0, %o0