diff --git a/CHANGELOG.md b/CHANGELOG.md index f3ac0bdc5..185f1aa6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Fixed * Guest libc accepts null buffers for zero-length writes. +* Fix calls to guest functions with more than 11 parameters. Registration accepts up to 32, but every call with more than 11 failed. ## [v0.18.0] - 2026-10-13 diff --git a/src/hyperlight_common/src/func/param_type.rs b/src/hyperlight_common/src/func/param_type.rs index 6fda13485..b0fbabadc 100644 --- a/src/hyperlight_common/src/func/param_type.rs +++ b/src/hyperlight_common/src/func/param_type.rs @@ -66,6 +66,29 @@ macro_rules! impl_supported_param_type { for_each_param_type!(impl_supported_param_type); /// A trait to describe the tuple of parameters that a host function can take. +/// +/// Functions take at most 32 parameters. +/// +/// ``` +/// fn takes() {} +/// takes::<( +/// i32, i32, i32, i32, i32, i32, i32, i32, +/// i32, i32, i32, i32, i32, i32, i32, i32, +/// i32, i32, i32, i32, i32, i32, i32, i32, +/// i32, i32, i32, i32, i32, i32, i32, i32, +/// )>(); +/// ``` +/// +/// ```compile_fail +/// fn takes() {} +/// takes::<( +/// i32, i32, i32, i32, i32, i32, i32, i32, +/// i32, i32, i32, i32, i32, i32, i32, i32, +/// i32, i32, i32, i32, i32, i32, i32, i32, +/// i32, i32, i32, i32, i32, i32, i32, i32, +/// i32, +/// )>(); +/// ``` pub trait ParameterTuple: Sized + Clone + Send + Sync + 'static { /// The number of parameters in the tuple const SIZE: usize; diff --git a/src/hyperlight_guest_bin/src/guest_function/definition.rs b/src/hyperlight_guest_bin/src/guest_function/definition.rs index e9763e8b1..dc23655d6 100644 --- a/src/hyperlight_guest_bin/src/guest_function/definition.rs +++ b/src/hyperlight_guest_bin/src/guest_function/definition.rs @@ -177,20 +177,6 @@ impl GuestFunctionDefinition { /// Verify that `self` has same signature as the provided `parameter_types`. pub fn verify_parameters(&self, parameter_types: &[ParameterType]) -> Result<()> { - // Verify that the function does not have more than `MAX_PARAMETERS` parameters. - const MAX_PARAMETERS: usize = 11; - if parameter_types.len() > MAX_PARAMETERS { - return Err(HyperlightGuestError::new( - ErrorCode::GuestError, - format!( - "Function {} has too many parameters: {} (max allowed is {}).", - self.function_name, - parameter_types.len(), - MAX_PARAMETERS - ), - )); - } - if self.parameter_types.len() != parameter_types.len() { return Err(HyperlightGuestError::new( ErrorCode::GuestFunctionIncorrecNoOfParameters, diff --git a/src/hyperlight_guest_macro/src/lib.rs b/src/hyperlight_guest_macro/src/lib.rs index bbee870ad..99992ceb0 100644 --- a/src/hyperlight_guest_macro/src/lib.rs +++ b/src/hyperlight_guest_macro/src/lib.rs @@ -37,7 +37,7 @@ impl Parse for NameArg { /// /// The function arguments must be supported parameter types, and the return type must be /// a supported return type or a `Result` with T being a supported -/// return type. +/// return type. Guest functions take at most 32 parameters, the limit `ParameterTuple` sets. /// /// # Note /// The function will be registered with the host at program initialization regardless of diff --git a/src/hyperlight_host/tests/sandbox_host_tests.rs b/src/hyperlight_host/tests/sandbox_host_tests.rs index 1064b1152..8cc658110 100644 --- a/src/hyperlight_host/tests/sandbox_host_tests.rs +++ b/src/hyperlight_host/tests/sandbox_host_tests.rs @@ -12,7 +12,7 @@ use hyperlight_testing::simple_guest_as_pathbuf; pub mod common; // pub to disable dead_code warning use crate::common::{ - with_all_guests, with_all_sandboxes, with_c_sandbox, with_c_sandbox_from, + with_all_guests, with_all_sandboxes, with_c_sandbox, with_c_sandbox_from, with_rust_sandbox, with_rust_uninit_sandbox, with_rust_uninit_sandbox_cfg, }; @@ -200,6 +200,24 @@ fn multiple_parameters() { }); } +#[test] +fn guest_function_with_thirty_two_parameters() { + with_rust_sandbox(|mut sandbox| { + let sum: i32 = sandbox + .call( + "SumThirtyTwoArgs", + ( + 1_i32, 2_i32, 3_i32, 4_i32, 5_i32, 6_i32, 7_i32, 8_i32, 9_i32, 10_i32, 11_i32, + 12_i32, 13_i32, 14_i32, 15_i32, 16_i32, 17_i32, 18_i32, 19_i32, 20_i32, 21_i32, + 22_i32, 23_i32, 24_i32, 25_i32, 26_i32, 27_i32, 28_i32, 29_i32, 30_i32, 31_i32, + 32_i32, + ), + ) + .unwrap(); + assert_eq!(sum, (1..=32).sum::()); + }); +} + #[test] fn incorrect_parameter_type() { with_all_sandboxes(|mut sandbox| { diff --git a/src/tests/rust_guests/simpleguest/src/main.rs b/src/tests/rust_guests/simpleguest/src/main.rs index 3753b276e..7f16e85f7 100644 --- a/src/tests/rust_guests/simpleguest/src/main.rs +++ b/src/tests/rust_guests/simpleguest/src/main.rs @@ -326,6 +326,13 @@ fn print_eleven_args(arg1: String, arg2: i32, arg3: i64, arg4: String, arg5: Str host_print(message) } +#[rustfmt::skip] +#[allow(clippy::too_many_arguments)] +#[guest_function("SumThirtyTwoArgs")] +fn sum_thirty_two_args(a1: i32, a2: i32, a3: i32, a4: i32, a5: i32, a6: i32, a7: i32, a8: i32, a9: i32, a10: i32, a11: i32, a12: i32, a13: i32, a14: i32, a15: i32, a16: i32, a17: i32, a18: i32, a19: i32, a20: i32, a21: i32, a22: i32, a23: i32, a24: i32, a25: i32, a26: i32, a27: i32, a28: i32, a29: i32, a30: i32, a31: i32, a32: i32) -> i32 { + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20 + a21 + a22 + a23 + a24 + a25 + a26 + a27 + a28 + a29 + a30 + a31 + a32 +} + #[guest_function("BufferOverrun")] fn buffer_overrun(value: String) -> i32 { let c_str = value.as_str();