Skip to content

Commit 49e248a

Browse files
authored
Only clear io buffer after unsuccesfull guest call (#811)
* Only clear io buffer after unsuccesfull guest call. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com> Undo stuff that breaks unwinding Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com> * Add error path to test Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com> --------- Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
1 parent 87af189 commit 49e248a

File tree

1 file changed

+32
-3
lines changed

1 file changed

+32
-3
lines changed

src/hyperlight_host/src/sandbox/initialized_multi_use.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,14 @@ impl MultiUseSandbox {
425425
.get_guest_function_call_result()
426426
})();
427427

428-
// TODO: Do we want to allow re-entrant guest function calls?
429-
self.get_mgr_wrapper_mut().as_mut().clear_io_buffers();
430-
428+
// In the happy path we do not need to clear io-buffers from the host because:
429+
// - the serialized guest function call is zeroed out by the guest during deserialization, see call to `try_pop_shared_input_data_into::<FunctionCall>()`
430+
// - the serialized guest function result is zeroed out by us (the host) during deserialization, see `get_guest_function_call_result`
431+
// - any serialized host function call are zeroed out by us (the host) during deserialization, see `get_host_function_call`
432+
// - any serialized host function result is zeroed out by the guest during deserialization, see `get_host_return_value`
433+
if res.is_err() {
434+
self.get_mgr_wrapper_mut().as_mut().clear_io_buffers();
435+
}
431436
res
432437
}
433438

@@ -497,6 +502,7 @@ mod tests {
497502
use std::sync::{Arc, Barrier};
498503
use std::thread;
499504

505+
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
500506
use hyperlight_testing::simple_guest_as_string;
501507

502508
#[cfg(target_os = "linux")]
@@ -506,6 +512,29 @@ mod tests {
506512
use crate::sandbox::SandboxConfiguration;
507513
use crate::{GuestBinary, HyperlightError, MultiUseSandbox, Result, UninitializedSandbox};
508514

515+
/// Make sure input/output buffers are properly reset after guest call (with host call)
516+
#[test]
517+
fn io_buffer_reset() {
518+
let mut cfg = SandboxConfiguration::default();
519+
cfg.set_input_data_size(4096);
520+
cfg.set_output_data_size(4096);
521+
let path = simple_guest_as_string().unwrap();
522+
let mut sandbox =
523+
UninitializedSandbox::new(GuestBinary::FilePath(path), Some(cfg)).unwrap();
524+
sandbox.register("HostAdd", |a: i32, b: i32| a + b).unwrap();
525+
let mut sandbox = sandbox.evolve().unwrap();
526+
527+
// will exhaust io if leaky. Tests both success and error paths
528+
for _ in 0..1000 {
529+
let result = sandbox.call::<i32>("Add", (5i32, 10i32)).unwrap();
530+
assert_eq!(result, 15);
531+
let result = sandbox.call::<i32>("AddToStaticAndFail", ()).unwrap_err();
532+
assert!(
533+
matches!(result, HyperlightError::GuestError (code, msg ) if code == ErrorCode::GuestError && msg == "Crash on purpose")
534+
);
535+
}
536+
}
537+
509538
/// Tests that call_guest_function_by_name restores the state correctly
510539
#[test]
511540
fn test_call_guest_function_by_name() {

0 commit comments

Comments
 (0)