From f9709d6f9268cf1ec9534710e48821b1c009c777 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Fri, 29 May 2026 01:06:23 +0000 Subject: [PATCH] ch-remote: Fix error message deserialization from JSON response server_api_error_display_modifier deserialized the JSON error response into a `Vec<&str>`. However, if the error message contained escaped characters, it could not deserialize it into a borrowed string `&str` because unescaping requires allocation. This resulted in a deserialization error and a failure to print the error chain. This change switches the deserialization target to `Vec` to allow allocation. Signed-off-by: Andrei Vagin --- cloud-hypervisor/src/bin/ch-remote.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cloud-hypervisor/src/bin/ch-remote.rs b/cloud-hypervisor/src/bin/ch-remote.rs index 0e022c3cd..22d81e26a 100644 --- a/cloud-hypervisor/src/bin/ch-remote.rs +++ b/cloud-hypervisor/src/bin/ch-remote.rs @@ -1247,7 +1247,7 @@ fn main() { let body = body.as_ref().map_or("", |body| body.as_str()); // Retrieve the list of error messages back. - let lines: Vec<&str> = match serde_json::from_str(body) { + let lines: Vec = match serde_json::from_str(body) { Ok(json) => json, Err(e) => { return Some(format!( @@ -1259,7 +1259,8 @@ fn main() { let error_status = format!("Server responded with {status_code:?}"); // Prepend the error status line to the lines iter. - let lines = std::iter::once(error_status.as_str()).chain(lines); + let lines = + std::iter::once(error_status.as_str()).chain(lines.iter().map(|s| s.as_str())); let error_msg_multiline = lines .enumerate() .map(|(index, error_msg)| (index + level, error_msg)) @@ -1321,4 +1322,17 @@ mod unit_tests { assert_args_sorted(|| command.get_arguments()); } } + + #[test] + fn test_error_deserialization() { + let body = r#"["Error from API","The VM could not be snapshotted","Cannot send VM snapshot","Failed to send migratable component snapshot","Destination is not a directory: \"/tmp/ch.dump\""]"#; + let lines: Result, _> = serde_json::from_str(body); + assert!(lines.is_ok()); + let lines = lines.unwrap(); + assert_eq!(lines.len(), 5); + assert_eq!( + lines[4], + r#"Destination is not a directory: "/tmp/ch.dump""# + ); + } }