From 3ab095663a4ee886bb1ac1aab2284af356b8da3c Mon Sep 17 00:00:00 2001 From: Mathieu Tarral Date: Thu, 10 Sep 2026 11:46:43 -0700 Subject: [PATCH] fix: avoid attr_value_t conversion of new_command result during init Module initialization registers the `init-tsffs` CLI command by passing a `new_command(...)` call to `run_python`. `SIM_run_python` converts the value of a trailing expression to an `attr_value_t`. Newer Simics Base versions return a `CliCommand` object from `new_command` instead of `None`, and that object has no `attr_value_t` representation, so the conversion raises `SimExc_Type`. The command is registered successfully; only the marshalling of the return value fails. `#[simics_exception]` turns that pending exception into an `Err`, which the error path then mishandles: let tsffs = Tsffs::create()?; // *mut ConfClass ... .map_err(|e| { error!(tsffs, "{e}"); e }) `simics::log!` casts its object argument with `$obj as *mut ConfObject`. `ConfClass` and `ConfObject` are distinct opaque types, so this raw pointer cast compiles silently and `VT_log_error` reads a `conf_class_t` as a `conf_object_t`. The result is a SIGSEGV inside `VT_effective_log_level` while loading the module, which hides the real error entirely: #3 VT_effective_log_level #4 VT_log_message64 #5 VT_log_error #6 simics::api::logging::log_error #7 _simics_module_init Bind the result of `new_command` to a variable so the snippet is a statement rather than an expression. No value is returned, so no conversion is attempted. Drop the `error!` call that passed a `ConfClass` where a `ConfObject` was required; the remaining `.expect()` reports any genuine failure without dereferencing an invalid pointer. Verified by loading the rebuilt module: `load-module tsffs` followed by `init-tsffs` now succeeds and creates the `tsffs` object. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/lib.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c660e2fb..95775e96 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1064,8 +1064,14 @@ fn init() { print("TSFFS initialized. Configure and use it as @tsffs.") "#}) .expect("Failed to run python"); + // NOTE: The result of `new_command` is bound to a variable so that this snippet is a + // statement rather than an expression. `SIM_run_python` converts the value of a trailing + // expression to an `attr_value_t`, and newer Simics Base versions return a `CliCommand` + // object from `new_command` rather than `None`. That object has no `attr_value_t` + // representation, so the conversion raises `SimExc_Type` even though the command itself + // was registered successfully. Binding the result avoids the conversion entirely. run_python(indoc! {r#" - new_command( + _tsffs_init_command = new_command( "init-tsffs", init_tsffs_cmd, [], @@ -1075,9 +1081,5 @@ fn init() { doc = "Initialize the TSFFS fuzzer" ) "#}) - .map_err(|e| { - error!(tsffs, "{e}"); - e - }) .expect("Failed to run python"); }