Loops with 'loop forever' annotation inside strcmp are actually meant to
loop forever. Falling through the end of the first loop may result in
equal strings being compared unequal, e.g.:

        #include <string.h>

        int main(void)
        {
                char a[4096] __attribute__((aligned(4)));
                char b[4096] __attribute__((aligned(4)));

                memset(a, ' ', 258 * 8);
                memset(b, ' ', 258 * 8);
                a[255 * 8] = 0;
                a[256 * 8] = 'a';
                b[255 * 8] = 0;
                b[256 * 8] = 'b';
                return !(strcmp(a, b) == 0);
        }

Falling through the end of the second loop may result in unequal strings
being compared as equal, e.g.:

        #include <string.h>

        int main(void)
        {
                char a[4096] __attribute__((aligned(4)));
                char b[4096] __attribute__((aligned(4)));

                memset(a, ' ', 514 * 6);
                memset(b, ' ', 514 * 6);
                a[514 * 6 + 0] = 'a';
                a[514 * 6 + 1] = 0;
                b[514 * 6 + 0] = 'b';
                b[514 * 6 + 1] = 0;
                return !(strcmp(a, b) != 0);
        }

Use 0 as a loop counter to make 2^32 - 1 iterations which is enough to
cover all addressable memory. While at it drop useless nop at the end of
the first loop and use a11 for all loop counters.

Signed-off-by: Max Filippov <jcmvb...@gmail.com>
---
Changes v1->v2:
- wrong test case for the second loop, fixed.

 libc/string/xtensa/strcmp.S | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/libc/string/xtensa/strcmp.S b/libc/string/xtensa/strcmp.S
index 2dce590dbd42..a16da5da2e92 100644
--- a/libc/string/xtensa/strcmp.S
+++ b/libc/string/xtensa/strcmp.S
@@ -92,8 +92,8 @@ ENTRY (strcmp)
        /* (2 mod 4) alignment for loop instruction */
 .Lunaligned:
 #if XCHAL_HAVE_LOOPS
-       _movi.n a8, 0           /* set up for the maximum loop count */
-       loop    a8, .Lretdiff   /* loop forever (almost anyway) */
+       movi    a11, 0          /* set up for the maximum loop count */
+       loop    a11, .Lretdiff  /* loop forever (almost anyway) */
 #endif
 .Lnextbyte:
        l8ui    a8, a2, 0
@@ -131,11 +131,10 @@ ENTRY (strcmp)
 #if XCHAL_HAVE_LOOPS
 .Laligned:
        .begin  no-transform
+       movi    a11, 0
        l32r    a4, .Lmask0     /* mask for byte 0 */
        l32r    a7, .Lmask4
-       /* Loop forever.  (a4 is more than than the maximum number
-          of iterations) */
-       loop    a4, .Laligned_done
+       loop    a11, .Laligned_done /* Loop forever. */
 
        /* First unrolled loop body.  */
        l32i    a8, a2, 0       /* get word from s1 */
@@ -156,8 +155,6 @@ ENTRY (strcmp)
        addi    a2, a2, 8       /* advance s1 pointer */
        addi    a3, a3, 8       /* advance s2 pointer */
 .Laligned_done:
-       or      a1, a1, a1      /* nop */
-
 .Lprobeq2:
        /* Adjust pointers to account for the loop unrolling.  */
        addi    a2, a2, 4
@@ -198,7 +195,7 @@ ENTRY (strcmp)
 #if XCHAL_HAVE_LOOPS
 
        /* align (1 mod 4) */
-       loop    a4, .Leq        /* loop forever (a4 is bigger than max iters) */
+       loop    a11, .Leq       /* loop forever */
        .end    no-transform
 
        l32i    a8, a2, 0       /* get word from s1 */
-- 
2.1.4

_______________________________________________
devel mailing list
devel@uclibc-ng.org
https://mailman.uclibc-ng.org/cgi-bin/mailman/listinfo/devel

Reply via email to