diff --git a/crates/console/prometeu-vm/src/virtual_machine.rs b/crates/console/prometeu-vm/src/virtual_machine.rs index e792b175..b207c8af 100644 --- a/crates/console/prometeu-vm/src/virtual_machine.rs +++ b/crates/console/prometeu-vm/src/virtual_machine.rs @@ -2907,6 +2907,128 @@ mod tests { ); } + #[test] + fn test_loader_patching_propagates_missing_capability() { + let mut vm = VirtualMachine::default(); + vm.set_capabilities(prometeu_hal::syscalls::caps::NONE); + + let code = assemble("HOSTCALL 0\nHALT").expect("assemble"); + let bytes = serialized_single_function_module( + code, + vec![SyscallDecl { + module: "gfx".into(), + name: "clear".into(), + version: 1, + arg_slots: 1, + ret_slots: 0, + }], + ); + + let res = vm.initialize(bytes, ""); + + assert_eq!( + res, + Err(VmInitError::LoaderPatchFailed( + crate::vm_init_error::LoaderPatchError::ResolveFailed( + prometeu_hal::syscalls::DeclaredLoadError::MissingCapability { + required: prometeu_hal::syscalls::caps::GFX, + provided: prometeu_hal::syscalls::caps::NONE, + module: "gfx".into(), + name: "clear".into(), + version: 1, + }, + ), + )) + ); + } + + #[test] + fn test_loader_patching_propagates_abi_mismatch() { + let mut vm = VirtualMachine::default(); + vm.set_capabilities(prometeu_hal::syscalls::caps::GFX); + + let code = assemble("HOSTCALL 0\nHALT").expect("assemble"); + let bytes = serialized_single_function_module( + code, + vec![SyscallDecl { + module: "gfx".into(), + name: "draw_line".into(), + version: 1, + arg_slots: 4, + ret_slots: 0, + }], + ); + + let res = vm.initialize(bytes, ""); + + assert_eq!( + res, + Err(VmInitError::LoaderPatchFailed( + crate::vm_init_error::LoaderPatchError::ResolveFailed( + prometeu_hal::syscalls::DeclaredLoadError::AbiMismatch { + module: "gfx".into(), + name: "draw_line".into(), + version: 1, + declared_arg_slots: 4, + declared_ret_slots: 0, + expected_arg_slots: 5, + expected_ret_slots: 0, + }, + ), + )) + ); + } + + #[test] + fn test_loader_hardening_missing_sysc_section() { + let mut vm = VirtualMachine::default(); + let mut header = vec![0u8; 32]; + header[0..4].copy_from_slice(b"PBS\0"); + + let res = vm.initialize(header, ""); + + assert_eq!( + res, + Err(VmInitError::ImageLoadFailed( + prometeu_bytecode::LoadError::MissingSyscallSection + )) + ); + } + + #[test] + fn test_loader_hardening_duplicate_sysc_identity() { + let mut vm = VirtualMachine::default(); + + let bytes = serialized_single_function_module( + vec![], + vec![ + SyscallDecl { + module: "system".into(), + name: "has_cart".into(), + version: 1, + arg_slots: 0, + ret_slots: 1, + }, + SyscallDecl { + module: "system".into(), + name: "has_cart".into(), + version: 1, + arg_slots: 0, + ret_slots: 1, + }, + ], + ); + + let res = vm.initialize(bytes, ""); + + assert_eq!( + res, + Err(VmInitError::ImageLoadFailed( + prometeu_bytecode::LoadError::DuplicateSyscallIdentity + )) + ); + } + #[test] fn test_calling_convention_add() { let mut native = MockNative;