mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-26 20:41:08 +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:
parent
6820964e2f
commit
9404dbf74e
|
@ -395,7 +395,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||||
|
|
||||||
/* execute the generated code */
|
/* execute the generated code */
|
||||||
ret = cpu_tb_exec(cpu, tb);
|
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;
|
*tb_exit = ret & TB_EXIT_MASK;
|
||||||
switch (*tb_exit) {
|
switch (*tb_exit) {
|
||||||
case TB_EXIT_REQUESTED:
|
case TB_EXIT_REQUESTED:
|
||||||
|
@ -419,6 +419,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||||
abort();
|
abort();
|
||||||
#else
|
#else
|
||||||
int insns_left = cpu->icount_decr.u32;
|
int insns_left = cpu->icount_decr.u32;
|
||||||
|
*last_tb = NULL;
|
||||||
if (cpu->icount_extra && insns_left >= 0) {
|
if (cpu->icount_extra && insns_left >= 0) {
|
||||||
/* Refill decrementer and continue execution. */
|
/* Refill decrementer and continue execution. */
|
||||||
cpu->icount_extra += insns_left;
|
cpu->icount_extra += insns_left;
|
||||||
|
@ -428,18 +429,18 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||||
} else {
|
} else {
|
||||||
if (insns_left > 0) {
|
if (insns_left > 0) {
|
||||||
/* Execute remaining instructions. */
|
/* Execute remaining instructions. */
|
||||||
cpu_exec_nocache(cpu, insns_left, *last_tb, false);
|
cpu_exec_nocache(cpu, insns_left, tb, false);
|
||||||
// Unicorn: commented out
|
// Unicorn: commented out
|
||||||
//align_clocks(sc, cpu);
|
//align_clocks(sc, cpu);
|
||||||
}
|
}
|
||||||
cpu->exception_index = EXCP_INTERRUPT;
|
cpu->exception_index = EXCP_INTERRUPT;
|
||||||
*last_tb = NULL;
|
|
||||||
cpu_loop_exit(cpu);
|
cpu_loop_exit(cpu);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
*last_tb = tb;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,6 +338,7 @@ static inline void tb_set_jmp_target(TranslationBlock *tb,
|
||||||
static inline void tb_add_jump(TranslationBlock *tb, int n,
|
static inline void tb_add_jump(TranslationBlock *tb, int n,
|
||||||
TranslationBlock *tb_next)
|
TranslationBlock *tb_next)
|
||||||
{
|
{
|
||||||
|
assert(n < ARRAY_SIZE(tb->jmp_list_next));
|
||||||
if (tb->jmp_list_next[n]) {
|
if (tb->jmp_list_next[n]) {
|
||||||
/* Another thread has already done this while we were
|
/* Another thread has already done this while we were
|
||||||
* outside of the lock; nothing to do in this case */
|
* outside of the lock; nothing to do in this case */
|
||||||
|
|
Loading…
Reference in a new issue