fix uc_mem write with cow when using upper half of the address
uc->target_page_align is a uint32_t. When the binary not will only invert the 32 bit of the value. Used this in a binary and operator with a uint64_t will case the upper 32bit of the address to be 0. Therefor the bug only appears when the upper 32bit of the address are used. Now a local uint64_t variable is used for the alignemend and the test uses a not page alligned address which does not fit in 32bit.
This commit is contained in:
parent
5e39cc602a
commit
d9d2c4e581
@ -379,27 +379,29 @@ static void test_context_snapshot(void)
|
|||||||
{
|
{
|
||||||
uc_engine *uc;
|
uc_engine *uc;
|
||||||
uc_context *ctx;
|
uc_context *ctx;
|
||||||
|
uint64_t baseaddr = 0xfffff1000;
|
||||||
|
uint64_t offset = 0x10;
|
||||||
uint64_t tmp = 1;
|
uint64_t tmp = 1;
|
||||||
|
|
||||||
OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc));
|
OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc));
|
||||||
OK(uc_ctl_context_mode(uc, UC_CTL_CONTEXT_MEMORY | UC_CTL_CONTEXT_CPU));
|
OK(uc_ctl_context_mode(uc, UC_CTL_CONTEXT_MEMORY | UC_CTL_CONTEXT_CPU));
|
||||||
OK(uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL));
|
OK(uc_mem_map(uc, baseaddr, 0x1000, UC_PROT_ALL));
|
||||||
OK(uc_context_alloc(uc, &ctx));
|
OK(uc_context_alloc(uc, &ctx));
|
||||||
OK(uc_context_save(uc, ctx));
|
OK(uc_context_save(uc, ctx));
|
||||||
|
|
||||||
OK(uc_mem_write(uc, 0x1000, &tmp, sizeof(tmp)));
|
OK(uc_mem_write(uc, baseaddr + offset, &tmp, sizeof(tmp)));
|
||||||
OK(uc_mem_read(uc, 0x1000, &tmp, sizeof(tmp)));
|
OK(uc_mem_read(uc, baseaddr + offset, &tmp, sizeof(tmp)));
|
||||||
TEST_CHECK(tmp == 1);
|
TEST_CHECK(tmp == 1);
|
||||||
OK(uc_context_restore(uc, ctx));
|
OK(uc_context_restore(uc, ctx));
|
||||||
OK(uc_mem_read(uc, 0x1000, &tmp, sizeof(tmp)));
|
OK(uc_mem_read(uc, baseaddr + offset, &tmp, sizeof(tmp)));
|
||||||
TEST_CHECK(tmp == 0);
|
TEST_CHECK(tmp == 0);
|
||||||
|
|
||||||
tmp = 2;
|
tmp = 2;
|
||||||
OK(uc_mem_write(uc, 0x1000, &tmp, sizeof(tmp)));
|
OK(uc_mem_write(uc, baseaddr + offset, &tmp, sizeof(tmp)));
|
||||||
OK(uc_mem_read(uc, 0x1000, &tmp, sizeof(tmp)));
|
OK(uc_mem_read(uc, baseaddr + offset, &tmp, sizeof(tmp)));
|
||||||
TEST_CHECK(tmp == 2);
|
TEST_CHECK(tmp == 2);
|
||||||
OK(uc_context_restore(uc, ctx));
|
OK(uc_context_restore(uc, ctx));
|
||||||
OK(uc_mem_read(uc, 0x1000, &tmp, sizeof(tmp)));
|
OK(uc_mem_read(uc, baseaddr + offset, &tmp, sizeof(tmp)));
|
||||||
TEST_CHECK(tmp == 0);
|
TEST_CHECK(tmp == 0);
|
||||||
|
|
||||||
OK(uc_context_free(ctx));
|
OK(uc_context_free(ctx));
|
||||||
|
7
uc.c
7
uc.c
@ -780,6 +780,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes,
|
|||||||
MemoryRegion *mr = uc->memory_mapping(uc, address);
|
MemoryRegion *mr = uc->memory_mapping(uc, address);
|
||||||
if (mr) {
|
if (mr) {
|
||||||
uint32_t operms = mr->perms;
|
uint32_t operms = mr->perms;
|
||||||
|
uint64_t align = uc->target_page_align;
|
||||||
if (!(operms & UC_PROT_WRITE)) { // write protected
|
if (!(operms & UC_PROT_WRITE)) { // write protected
|
||||||
// but this is not the program accessing memory, so temporarily
|
// but this is not the program accessing memory, so temporarily
|
||||||
// mark writable
|
// mark writable
|
||||||
@ -788,10 +789,8 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes,
|
|||||||
|
|
||||||
len = memory_region_len(uc, mr, address, size - count);
|
len = memory_region_len(uc, mr, address, size - count);
|
||||||
if (uc->snapshot_level && uc->snapshot_level > mr->priority) {
|
if (uc->snapshot_level && uc->snapshot_level > mr->priority) {
|
||||||
mr = uc->memory_cow(uc, mr, address & ~uc->target_page_align,
|
mr = uc->memory_cow(uc, mr, address & ~align,
|
||||||
(len + (address & uc->target_page_align) +
|
(len + (address & align) + align) & ~align);
|
||||||
uc->target_page_align) &
|
|
||||||
~uc->target_page_align);
|
|
||||||
if (!mr) {
|
if (!mr) {
|
||||||
return UC_ERR_NOMEM;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user