From ef9bd0b8d7d0a70f9fa9b239a03099c57eb5ceea Mon Sep 17 00:00:00 2001 From: Yao Qi Date: Mon, 16 Nov 2015 14:44:19 +0000 Subject: [PATCH] Fix bug in arm_push_dummy_call by -fsanitize=address When I build GDB with -fsanitize=address, and run testsuite, some gdb.base/*.exp test triggers the ERROR below, ================================================================= ==7646==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000242810 at pc 0x487844 bp 0x7fffe32e84e0 sp 0x7fffe32e84d8 READ of size 4 at 0x603000242810 thread T0 #0 0x487843 in push_stack_item /home/yao/SourceCode/gnu/gdb/git/gdb/arm-tdep.c:3405 #1 0x48998a in arm_push_dummy_call /home/yao/SourceCode/gnu/gdb/git/gdb/arm-tdep.c:3960 In that path, GDB passes value on stack, in an INT_REGISTER_SIZE slot, but the value contents' length can be less than INT_REGISTER_SIZE, so the contents will be accessed out of the bound. This patch adds an array buf[INT_REGISTER_SIZE], and copy val to buf before writing them to stack. gdb: 2015-11-16 Yao Qi * arm-tdep.c (arm_push_dummy_call): New array buf. Store regval to buf. Pass buf instead of val to push_stack_item. --- gdb/ChangeLog | 5 +++++ gdb/arm-tdep.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e48ffa1c5c6..2b2409a4271 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2015-11-16 Yao Qi + + * arm-tdep.c (arm_push_dummy_call): New array buf. Store regval + to buf. Pass buf instead of val to push_stack_item. + 2015-11-13 Yao Qi PR tdep/19051 diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index b8f84ce9d04..ef1a0077478 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -3925,13 +3925,13 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function, while (len > 0) { int partial_len = len < INT_REGISTER_SIZE ? len : INT_REGISTER_SIZE; + CORE_ADDR regval + = extract_unsigned_integer (val, partial_len, byte_order); if (may_use_core_reg && argreg <= ARM_LAST_ARG_REGNUM) { /* The argument is being passed in a general purpose register. */ - CORE_ADDR regval - = extract_unsigned_integer (val, partial_len, byte_order); if (byte_order == BFD_ENDIAN_BIG) regval <<= (INT_REGISTER_SIZE - partial_len) * 8; if (arm_debug) @@ -3945,11 +3945,16 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } else { + gdb_byte buf[INT_REGISTER_SIZE]; + + memset (buf, 0, sizeof (buf)); + store_unsigned_integer (buf, partial_len, byte_order, regval); + /* Push the arguments onto the stack. */ if (arm_debug) fprintf_unfiltered (gdb_stdlog, "arg %d @ sp + %d\n", argnum, nstack); - si = push_stack_item (si, val, INT_REGISTER_SIZE); + si = push_stack_item (si, buf, INT_REGISTER_SIZE); nstack += INT_REGISTER_SIZE; }