gpu: Fix context name parsing for non-null-terminated strings

Use String::from_utf8_lossy() instead of CStr::from_bytes_with_nul()
since the virtio-gpu driver sends debug_name without null terminator.

Signed-off-by: Matej Hrica <mhrica@redhat.com>
This commit is contained in:
Matej Hrica 2025-12-09 17:18:20 +01:00
parent 0eae1f2274
commit c7ce8cd7f9
2 changed files with 26 additions and 16 deletions

View File

@ -359,11 +359,11 @@ impl VhostUserGpuBackendInner {
hdr: virtio_gpu_ctrl_hdr,
req: virtio_gpu_ctx_create,
) -> VirtioGpuResult {
let context_name: Option<String> = Some(req.get_debug_name());
let context_name = req.get_debug_name();
renderer.create_context(
hdr.ctx_id.into(),
req.context_init.into(),
context_name.as_deref(),
Some(&context_name),
)
}

View File

@ -6,9 +6,9 @@
#![allow(non_camel_case_types)]
use std::{
borrow::Cow,
cmp::min,
convert::From,
ffi::CStr,
fmt::{self, Display},
io::{self, Read, Write},
marker::PhantomData,
@ -441,14 +441,9 @@ impl Default for virtio_gpu_ctx_create {
}
impl virtio_gpu_ctx_create {
pub fn get_debug_name(&self) -> String {
CStr::from_bytes_with_nul(
&self.debug_name[..min(64, <Le32 as Into<u32>>::into(self.nlen) as usize)],
)
.map_or_else(
|err| format!("Err({err})"),
|c_str| c_str.to_string_lossy().into_owned(),
)
pub fn get_debug_name(&self) -> Cow<'_, str> {
let len = min(64, <Le32 as Into<u32>>::into(self.nlen) as usize);
String::from_utf8_lossy(&self.debug_name[..len])
}
}
impl fmt::Debug for virtio_gpu_ctx_create {
@ -1355,8 +1350,9 @@ mod tests {
#[test]
fn test_virtio_gpu_ctx_create_debug() {
let bytes = b"test_debug\0";
let original = virtio_gpu_ctx_create {
// Test without null terminator (typical case)
let bytes = b"test_debug";
let ctx = virtio_gpu_ctx_create {
debug_name: {
let mut debug_name = [0; 64];
debug_name[..bytes.len()].copy_from_slice(bytes);
@ -1365,12 +1361,26 @@ mod tests {
context_init: 0.into(),
nlen: (bytes.len() as u32).into(),
};
let debug_string = format!("{original:?}");
assert_eq!(
debug_string,
format!("{ctx:?}"),
"virtio_gpu_ctx_create { debug_name: \"test_debug\", context_init: Le32(0), .. }"
);
// Test with null terminator included in nlen (edge case - should preserve it)
let bytes_with_null = b"test_debug\0";
let ctx_with_null = virtio_gpu_ctx_create {
debug_name: {
let mut debug_name = [0; 64];
debug_name[..bytes_with_null.len()].copy_from_slice(bytes_with_null);
debug_name
},
context_init: 0.into(),
nlen: (bytes_with_null.len() as u32).into(),
};
assert_eq!(
format!("{ctx_with_null:?}"),
"virtio_gpu_ctx_create { debug_name: \"test_debug\\0\", context_init: Le32(0), .. }"
);
}
#[test]