From e7bc1773a7e080a857d2b9de32d2df9b28858a72 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Thu, 14 Sep 2023 10:56:36 +0000 Subject: [PATCH] jit: correctly load the StableResult discriminant in emit_result_is_err StableResult is #[repr(C, u64)] which means that the layout is [u64 discriminant] [union of all the data carried by the variants] We were accessing the data of the Ok variant. --- src/jit.rs | 4 ++-- src/vm.rs | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/jit.rs b/src/jit.rs index 7c5038f2..b309cbf3 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -1279,9 +1279,9 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { fn emit_result_is_err(&mut self, destination: u8) { let ok = ProgramResult::Ok(0); - let err_kind = unsafe { *(&ok as *const _ as *const u64).add(1) }; + let ok_discriminant = ok.discriminant(); self.emit_ins(X86Instruction::lea(OperandSize::S64, RBP, destination, Some(X86IndirectAccess::Offset(self.slot_on_environment_stack(RuntimeEnvironmentSlot::ProgramResult))))); - self.emit_ins(X86Instruction::cmp_immediate(OperandSize::S64, destination, err_kind as i64, Some(X86IndirectAccess::Offset(0)))); + self.emit_ins(X86Instruction::cmp_immediate(OperandSize::S64, destination, ok_discriminant as i64, Some(X86IndirectAccess::Offset(0)))); } fn emit_subroutines(&mut self) { diff --git a/src/vm.rs b/src/vm.rs index db4d0d3f..e1745565 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -64,6 +64,18 @@ impl StableResult { Self::Err(error) => error, } } + + #[cfg_attr( + any( + not(feature = "jit"), + target_os = "windows", + not(target_arch = "x86_64") + ), + allow(dead_code) + )] + pub(crate) fn discriminant(&self) -> u64 { + unsafe { *(self as *const _ as *const u64) } + } } impl From> for Result { @@ -558,9 +570,9 @@ mod tests { #[test] fn test_program_result_is_stable() { let ok = ProgramResult::Ok(42); - assert_eq!(unsafe { *(&ok as *const _ as *const u64) }, 0); + assert_eq!(ok.discriminant(), 0); let err = ProgramResult::Err(Box::new(EbpfError::JitNotCompiled)); - assert_eq!(unsafe { *(&err as *const _ as *const u64) }, 1); + assert_eq!(err.discriminant(), 1); } #[test]