diff --git a/src/hyperlight_host/src/sandbox/initialized_multi_use.rs b/src/hyperlight_host/src/sandbox/initialized_multi_use.rs index 3c206dc65..44cd4e676 100644 --- a/src/hyperlight_host/src/sandbox/initialized_multi_use.rs +++ b/src/hyperlight_host/src/sandbox/initialized_multi_use.rs @@ -733,6 +733,9 @@ impl MultiUseSandbox { } })(); + // Clear partial abort bytes so they don't leak across calls. + self.mem_mgr.abort_buffer.clear(); + // In the happy path we do not need to clear io-buffers from the host because: // - the serialized guest function call is zeroed out by the guest during deserialization, see call to `try_pop_shared_input_data_into::()` // - the serialized guest function result is zeroed out by us (the host) during deserialization, see `get_guest_function_call_result` @@ -1464,6 +1467,33 @@ mod tests { ); } + /// Test that stale abort buffer bytes from a previous call don't + /// leak into the next call. + #[test] + fn stale_abort_buffer_does_not_leak_across_calls() { + let mut sbox: MultiUseSandbox = { + let path = simple_guest_as_string().unwrap(); + let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); + u_sbox.evolve().unwrap() + }; + + // Simulate a partial abort + sbox.mem_mgr.abort_buffer.extend_from_slice(&[0xAA; 1020]); + + let res = sbox.call::("Echo", "hello".to_string()); + assert!( + res.is_ok(), + "Expected Ok after stale abort buffer, got: {:?}", + res.unwrap_err() + ); + + // The buffer should be empty after the call. + assert!( + sbox.mem_mgr.abort_buffer.is_empty(), + "abort_buffer should be empty after a guest call" + ); + } + /// Test that sandboxes can be created and evolved with different heap sizes #[test] fn test_sandbox_creation_various_sizes() {