commit e3848e3dd64a8d6437531488fe341354bc02eaed
Author: Lucian Cojocar <lucian.cojocar@vu.nl>
Date:   Fri Jun 10 18:44:44 2016 +0200

    bugfix: ARM: memset.S: use unsigned comparisons
    
    The 'BLT' instruction checks for *signed* values. So if a3, length
    parameter of memset, is negative, then value added to the PC will be
    large.
    
    memset(buf, 0xaa, 0xffff0000) triggers the bug.
    
    GDB session without the patch:
    
    """
    $ gdb ./main-buggy-memset.elf -q
    Reading symbols from ./main-buggy-memset.elf...done.
    (gdb) x/i memset
       0x8770 <memset>:     mov     r3, r0
    (gdb) r
    Starting program: /root/memset/main-buggy-memset.elf
    
    Program received signal SIGSEGV, Segmentation fault.
    0x00048808 in ?? ()
    """
    
    The $pc is outside of the memset function because:
    
    """
    (gdb) x/i $pc
    => 0x87e4 <memset+116>: add     pc, pc, r2, lsl #2
    (gdb) info reg $r2
    r2             0x10007  65543
    """
    
    GDB session with the bug fixed (patch applied):
    
    """
    $ gdb ./main-fixed-memset.elf -q
    Reading symbols from ./main-fixed-memset.elf...done.
    (gdb) x/i memset
       0x8770 <memset>:     mov     r3, r0
    (gdb) r
    Starting program: /root/memset/main-fixed-memset.elf
    
    Program received signal SIGSEGV, Segmentation fault.
    memset () at libc/string/arm/memset.S:92
    92      libc/string/arm/memset.S: No such file or directory.
    (gdb) x/i $pc
    => 0x87b0 <memset+64>:  stmia   r3!, {r1, r12}
    (gdb) info reg $r3
    r3             0x15000  86016
    (gdb) info proc mappings
    process 5822
    Mapped address spaces:
    
            Start Addr   End Addr       Size     Offset objfile
                0x8000     0xb000     0x3000        0x0
    /root/memset/main-fixed-memset.elf
               0x12000    0x15000     0x3000     0x2000
    /root/memset/main-fixed-memset.elf
            0xb6fff000 0xb7000000     0x1000        0x0 [sigpage]
            0xbefdf000 0xbf000000    0x21000        0x0
            0xffff0000 0xffff1000     0x1000        0x0 [vectors]
    (gdb) info reg $sp
    sp             0x14d78  0x14d78
    """
    
    GDB crashes inside the memset function, on the store instruction.  This
    time the crash is (as expected) because of a memory access imediately
    after the memory region that contains the stack -- the buffer that's
    being memset'd is allocated on the stack.
    
    Signed-off-by: Lucian Cojocar <lucian.cojocar@vu.nl>

--- libc/string/arm/memset.S
+++ libc/string/arm/memset.S
@@ -67,7 +67,7 @@
 memset:
 	mov	a4, a1
 	cmp	a3, $8		@ at least 8 bytes to do?
-	blt	2f
+	blo	2f
 	orr	a2, a2, a2, lsl $8
 	orr	a2, a2, a2, lsl $16
 1:
@@ -84,27 +84,27 @@
 	mov	ip, a2
 1:
 	cmp	a3, $8		@ 8 bytes still to do?
-	blt	2f
+	blo	2f
 	stmia	a4!, {a2, ip}
 	sub	a3, a3, $8
 	cmp	a3, $8		@ 8 bytes still to do?
-	blt	2f
+	blo	2f
 	stmia	a4!, {a2, ip}
 	sub	a3, a3, $8
 	cmp	a3, $8		@ 8 bytes still to do?
-	blt	2f
+	blo	2f
 	stmia	a4!, {a2, ip}
 	sub	a3, a3, $8
 	cmp	a3, $8		@ 8 bytes still to do?
 #if defined(__thumb2__)
-	itt	ge
-	stmiage	a4!, {a2, ip}
-	subge	a3, a3, $8
+	itt	hs
+	stmiahs	a4!, {a2, ip}
+	subhs	a3, a3, $8
 #else
-	stmgeia	a4!, {a2, ip}
-	subge	a3, a3, $8
+	stmhsia	a4!, {a2, ip}
+	subhs	a3, a3, $8
 #endif
-	bge	1b
+	bhs	1b
 2:
 	movs	a3, a3		@ anything left?
 	IT(t, eq)
