diff options
author | Markus Armbruster | 2020-04-22 15:07:08 +0200 |
---|---|---|
committer | Markus Armbruster | 2020-04-29 08:01:52 +0200 |
commit | abc9bf69a66a11499a801ff545b8fe7adbb3a04c (patch) | |
tree | 736e0b8fb8494c84a24ce2740bcaa086cb3ddd5b | |
parent | block/file-posix: Fix check_cache_dropped() error handling (diff) | |
download | qemu-abc9bf69a66a11499a801ff545b8fe7adbb3a04c.tar.gz qemu-abc9bf69a66a11499a801ff545b8fe7adbb3a04c.tar.xz qemu-abc9bf69a66a11499a801ff545b8fe7adbb3a04c.zip |
cpus: Fix configure_icount() error API violation
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call.
configure_icount() is wrong that way. Harmless, because its @errp is
always &error_abort or &error_fatal.
Just as wrong (and just as harmless): when it fails, it can still
update global state.
Fix all that.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20200422130719.28225-4-armbru@redhat.com>
-rw-r--r-- | cpus.c | 45 |
1 files changed, 27 insertions, 18 deletions
@@ -797,40 +797,49 @@ void cpu_ticks_init(void) void configure_icount(QemuOpts *opts, Error **errp) { - const char *option; + const char *option = qemu_opt_get(opts, "shift"); + bool sleep = qemu_opt_get_bool(opts, "sleep", true); + bool align = qemu_opt_get_bool(opts, "align", false); + long time_shift = -1; char *rem_str = NULL; - option = qemu_opt_get(opts, "shift"); - if (!option) { - if (qemu_opt_get(opts, "align") != NULL) { - error_setg(errp, "Please specify shift option when using align"); - } + if (!option && qemu_opt_get(opts, "align")) { + error_setg(errp, "Please specify shift option when using align"); return; } - icount_sleep = qemu_opt_get_bool(opts, "sleep", true); - if (icount_sleep) { - timers_state.icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, - icount_timer_cb, NULL); - } - - icount_align_option = qemu_opt_get_bool(opts, "align", false); - - if (icount_align_option && !icount_sleep) { + if (align && !sleep) { error_setg(errp, "align=on and sleep=off are incompatible"); + return; } + if (strcmp(option, "auto") != 0) { errno = 0; - timers_state.icount_time_shift = strtol(option, &rem_str, 0); + time_shift = strtol(option, &rem_str, 0); if (errno != 0 || *rem_str != '\0' || !strlen(option)) { error_setg(errp, "icount: Invalid shift value"); + return; } - use_icount = 1; - return; } else if (icount_align_option) { error_setg(errp, "shift=auto and align=on are incompatible"); + return; } else if (!icount_sleep) { error_setg(errp, "shift=auto and sleep=off are incompatible"); + return; + } + + icount_sleep = sleep; + if (icount_sleep) { + timers_state.icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, + icount_timer_cb, NULL); + } + + icount_align_option = align; + + if (time_shift >= 0) { + timers_state.icount_time_shift = time_shift; + use_icount = 1; + return; } use_icount = 2; |