summaryrefslogtreecommitdiff
path: root/libc/string/arm
diff options
context:
space:
mode:
authorLucian Cojocar <lucian.cojocar@vu.nl>2016-06-10 18:44:44 +0200
committerWaldemar Brodkorb <wbx@uclibc-ng.org>2016-06-19 23:34:02 +0200
commite3848e3dd64a8d6437531488fe341354bc02eaed (patch)
treec72a7d20027421f46721fe067df3acc426943af1 /libc/string/arm
parent040632792e9f19ccf49149e4ae3ddac351a98b5a (diff)
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>
Diffstat (limited to 'libc/string/arm')
-rw-r--r--libc/string/arm/memset.S20
1 files changed, 10 insertions, 10 deletions
diff --git a/libc/string/arm/memset.S b/libc/string/arm/memset.S
index 2be4850e4..412270f50 100644
--- a/libc/string/arm/memset.S
+++ b/libc/string/arm/memset.S
@@ -67,7 +67,7 @@ memset:
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 @@ memset:
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)