You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The code in [1] incorrectly branches when compiled with the following command on Linux (assuming the code is in a file called sprintf.c):
arm-linux-gnueabi-gcc -o sprintf-arm -c sprintf.c
The bug can be triggered by running the Python code contained in [2]. When the code is run, the output contains the following snippet:
Executing instruction at 0x00000078
Executing instruction at 0x0000007c
Executing instruction at 0x00000080
Executing instruction at 0x000000cc
Executing instruction at 0x00000148
Executing instruction at 0x0000014c
The first three instructions are for the switch statement. However, instruction 0xcc is the branch instruction at the end of the case 1 block. I would expect the output to be the following:
Executing instruction at 0x00000078
Executing instruction at 0x0000007c
Executing instruction at 0x00000080
Executing instruction at 0x00000100
This is because instruction 0x100 is the start of the case 4 block, which the Python code sets up with the line uc.reg_write(uarm.UC_ARM_REG_R2, 4). If you compile [1] with arm-linux-gnueabi-gcc -o sprintf-arm-exe -DINCLUDE_MAIN sprintf.c, and run it in QEMU, the output is correct. I am using the pip version of unicorn for the python bindings.
$ pip show unicorn
Name: unicorn
Version: 1.0.1
Summary: Unicorn CPU emulator engine
Home-page: http://www.unicorn-engine.org
Author: Nguyen Anh Quynh
Author-email: [email protected]
License: UNKNOWN
Location: /usr/local/lib/python2.7/dist-packages
Requires:
Required-by:
Please let me know if there is more information I can provide.
[1]
#include <stddef.h>
/* Purposefully simplify sprintf for testing purposes.
* Format string is expected to have only %d and in is
* expected to be [0,5].
*/
int sprintf_simple(char* str, const char* fmt, int in) {
int i = 0;
int j = 0;
while(fmt[i] != '\0') {
if(fmt[i] == '%') {
/*if(in == 0) { str[j] = '0'; }
else if (in == 1) { str[j] = '1'; }
else if (in == 2) { str[j] = '2'; }
else if (in == 3) { str[j] = '3'; }
else if (in == 4) { str[j] = '4'; }
else if (in == 5) { str[j] = '5'; }
else { str[j] = '_'; }*/
switch(in) {
case 0:
str[j] = '0';
break;
case 1:
str[j] = '1';
break;
case 2:
str[j] = '2';
break;
case 3:
str[j] = '3';
break;
case 4:
str[j] = '4';
break;
case 5:
str[j] = '5';
break;
default:
str[j] = '_';
break;
}
/* Skip over %d */
i += 2;
j++;
continue;
}
str[j++] = fmt[i++];
}
str[j] = '\0';
return j + 1;
}
#ifdef INCLUDE_MAIN
#include <stdio.h>
int main(int argc, char** argv) {
char* fmt = "test %d";
char s[12];
printf("sprintf returned %d\n", sprintf_simple(s, fmt, 2));
printf("s = '%s'\n", s);
return 0;
}
#endif
[2]
import unicorn
import unicorn.arm_const as uarm
def code_hook(uc, address, size, user_data):
print "Executing instruction at 0x{:08x}".format(address)
if __name__ == "__main__":
uc = unicorn.Uc(unicorn.UC_ARCH_ARM, unicorn.UC_MODE_ARM)
with open("sprintf-arm", "rb") as fp:
binary = fp.read()
uc.mem_map(0, 5 * 1024 * 1024)
uc.mem_write(0, binary)
uc.hook_add(unicorn.UC_HOOK_CODE, code_hook)
uc.reg_write(uarm.UC_ARM_REG_SP, 0x270000)
uc.mem_write(0x250000, "test: %d")
# This value should be the start of sprint_simple
uc.reg_write(uarm.UC_ARM_REG_PC, 0x34)
uc.reg_write(uarm.UC_ARM_REG_R0, 0x260000)
uc.reg_write(uarm.UC_ARM_REG_R1, 0x250000)
uc.reg_write(uarm.UC_ARM_REG_R2, 4)
uc.reg_write(uarm.UC_ARM_REG_R3, 0)
uc.reg_write(uarm.UC_ARM_REG_R4, 0)
uc.reg_write(uarm.UC_ARM_REG_R5, 0)
uc.reg_write(uarm.UC_ARM_REG_R6, 0)
uc.reg_write(uarm.UC_ARM_REG_R7, 0)
uc.reg_write(uarm.UC_ARM_REG_R8, 0xFFFFFFFF)
uc.reg_write(uarm.UC_ARM_REG_R9, 0xFFFFFFFF)
uc.reg_write(uarm.UC_ARM_REG_R10, 0xFFFFFFFF)
uc.reg_write(uarm.UC_ARM_REG_R11, 0xFFFFFFFF)
uc.reg_write(uarm.UC_ARM_REG_LR, 0xFFFF)
uc.emu_start(uc.reg_read(uarm.UC_ARM_REG_PC), 0xFFFE, timeout=5000, count=0)
The text was updated successfully, but these errors were encountered:
The code in [1] incorrectly branches when compiled with the following command on Linux (assuming the code is in a file called
sprintf.c
):arm-linux-gnueabi-gcc -o sprintf-arm -c sprintf.c
The bug can be triggered by running the Python code contained in [2]. When the code is run, the output contains the following snippet:
The first three instructions are for the switch statement. However, instruction
0xcc
is the branch instruction at the end of thecase 1
block. I would expect the output to be the following:This is because instruction
0x100
is the start of thecase 4
block, which the Python code sets up with the lineuc.reg_write(uarm.UC_ARM_REG_R2, 4)
. If you compile [1] witharm-linux-gnueabi-gcc -o sprintf-arm-exe -DINCLUDE_MAIN sprintf.c
, and run it in QEMU, the output is correct. I am using the pip version of unicorn for the python bindings.Please let me know if there is more information I can provide.
[1]
[2]
The text was updated successfully, but these errors were encountered: