1
0
Fork 0
mirror of https://github.com/yuzu-emu/unicorn.git synced 2025-01-12 22:45:38 +00:00

cpu-exec: fix icount out-of-bounds access

When icount is active, tb_add_jump is surprisingly called with an
out of bounds basic block index. I have no idea how that can work,
but it does not seem like a good idea. Clear *last_tb for all
TB_EXIT_ICOUNT_EXPIRED cases, even when all you have to do is
refill icount_extra.

Backports commit d8dea6fbcbed177ca5d23ab77b3834a9437f0e88 from qemu
This commit is contained in:
Paolo Bonzini 2018-03-01 09:16:51 -05:00 committed by Lioncash
parent 6820964e2f
commit 9404dbf74e
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
2 changed files with 5 additions and 3 deletions
qemu

View file

@ -395,7 +395,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
/* execute the generated code */
ret = cpu_tb_exec(cpu, tb);
*last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
*tb_exit = ret & TB_EXIT_MASK;
switch (*tb_exit) {
case TB_EXIT_REQUESTED:
@ -419,6 +419,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
abort();
#else
int insns_left = cpu->icount_decr.u32;
*last_tb = NULL;
if (cpu->icount_extra && insns_left >= 0) {
/* Refill decrementer and continue execution. */
cpu->icount_extra += insns_left;
@ -428,18 +429,18 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
} else {
if (insns_left > 0) {
/* Execute remaining instructions. */
cpu_exec_nocache(cpu, insns_left, *last_tb, false);
cpu_exec_nocache(cpu, insns_left, tb, false);
// Unicorn: commented out
//align_clocks(sc, cpu);
}
cpu->exception_index = EXCP_INTERRUPT;
*last_tb = NULL;
cpu_loop_exit(cpu);
}
break;
#endif
}
default:
*last_tb = tb;
break;
}
}

View file

@ -338,6 +338,7 @@ static inline void tb_set_jmp_target(TranslationBlock *tb,
static inline void tb_add_jump(TranslationBlock *tb, int n,
TranslationBlock *tb_next)
{
assert(n < ARRAY_SIZE(tb->jmp_list_next));
if (tb->jmp_list_next[n]) {
/* Another thread has already done this while we were
* outside of the lock; nothing to do in this case */