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. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									d9ff1d35c5
								
							
						
					
					
						commit
						43d70ddf9f
					
				| 
						 | 
				
			
			@ -542,7 +542,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
 | 
			
		|||
 | 
			
		||||
    trace_exec_tb(tb, tb->pc);
 | 
			
		||||
    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:
 | 
			
		||||
| 
						 | 
				
			
			@ -566,6 +566,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -575,17 +576,17 @@ 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);
 | 
			
		||||
                align_clocks(sc, cpu);
 | 
			
		||||
            }
 | 
			
		||||
            cpu->exception_index = EXCP_INTERRUPT;
 | 
			
		||||
            *last_tb = NULL;
 | 
			
		||||
            cpu_loop_exit(cpu);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
        *last_tb = tb;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -318,6 +318,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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue