From cb4c173d20f1b762d8bb9e248f48641b6c67f852 Mon Sep 17 00:00:00 2001 From: Mason Reed Date: Tue, 9 Dec 2025 20:03:22 -0500 Subject: [PATCH] [Rust] Fix crash when calling `LowLevelILFunction::generate_ssa_form` without an owner You cannot generate SSA form of an LLIL function without a backing function unfortunately. --- rust/src/low_level_il/function.rs | 45 +++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/rust/src/low_level_il/function.rs b/rust/src/low_level_il/function.rs index 15a83c19e7..837b45efc2 100644 --- a/rust/src/low_level_il/function.rs +++ b/rust/src/low_level_il/function.rs @@ -213,6 +213,8 @@ where impl LowLevelILFunction { /// Retrieve the SSA form of the function. + /// + /// If the function has not had the SSA form generated you may call `generate_ssa_form`. pub fn ssa_form(&self) -> Option>> { let handle = unsafe { BNGetLowLevelILSSAForm(self.handle) }; if handle.is_null() { @@ -220,6 +222,29 @@ impl LowLevelILFunction { } Some(unsafe { LowLevelILFunction::ref_from_raw(handle) }) } + + /// Generates the SSA form of the function. Typically called **after** `finalize`. + /// + /// If you created a freestanding [`LowLevelILFunction`] with no [`LowLevelILFunction::function`] + /// than this function will **not** generate the SSA form, as it is currently impossible. + /// + /// # Example + /// + /// ```no_run + /// use binaryninja::low_level_il::LowLevelILMutableFunction; + /// use binaryninja::rc::Ref; + /// # let mutable_llil: Ref = unimplemented!(); + /// // ... modify the IL + /// let finalized_llil = mutable_llil.finalized(); + /// finalized_llil.generate_ssa_form(); + /// ``` + pub fn generate_ssa_form(&self) { + use binaryninjacore_sys::BNGenerateLowLevelILSSAForm; + // SSA form may only be generated if there is an owning function, otherwise it will crash. + if self.function().is_some() { + unsafe { BNGenerateLowLevelILSSAForm(self.handle) }; + } + } } // Allow instantiating Lifted IL functions for querying Lifted IL from Architectures @@ -242,14 +267,24 @@ impl LowLevelILFunction { unsafe { Self::ref_from_raw_with_arch(handle, Some(arch)) } } - - pub fn generate_ssa_form(&self) { - use binaryninjacore_sys::BNGenerateLowLevelILSSAForm; - unsafe { BNGenerateLowLevelILSSAForm(self.handle) }; - } } impl Ref> { + /// Finalize the mutated [`LowLevelILFunction`], returning a [`LowLevelILRegularFunction`]. + /// + /// This function **will not** correct the SSA related dataflow, to do that you must call + /// the function [`LowLevelILMutableFunction::generate_ssa_form`]. + /// + /// # Example + /// + /// ```no_run + /// use binaryninja::low_level_il::LowLevelILMutableFunction; + /// use binaryninja::rc::Ref; + /// # let mutable_llil: Ref = unimplemented!(); + /// // ... modify the IL + /// let finalized_llil = mutable_llil.finalized(); + /// finalized_llil.generate_ssa_form(); + /// ``` pub fn finalized(self) -> Ref> { unsafe { BNFinalizeLowLevelILFunction(self.handle);