From 3f0103f936a2d349b8f5f62df2a310e7079f2476 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 14 Aug 2018 17:10:49 +0200 Subject: [PATCH] Prevent finalize being called more than once per func/data (fixes #407) --- cranelift/tests/moduletests.rs | 52 ++++++++++++++++++++++++++++++++++ lib/module/src/module.rs | 10 +++++++ 2 files changed, 62 insertions(+) diff --git a/cranelift/tests/moduletests.rs b/cranelift/tests/moduletests.rs index 89a04e2cd5..1f4c9d204a 100644 --- a/cranelift/tests/moduletests.rs +++ b/cranelift/tests/moduletests.rs @@ -1,9 +1,14 @@ extern crate cranelift_codegen; +extern crate cranelift_entity; +extern crate cranelift_frontend; extern crate cranelift_module; extern crate cranelift_simplejit; use cranelift_codegen::ir::*; use cranelift_codegen::settings::*; +use cranelift_codegen::Context; +use cranelift_entity::EntityRef; +use cranelift_frontend::*; use cranelift_module::*; use cranelift_simplejit::*; @@ -25,3 +30,50 @@ fn error_on_incompatible_sig_in_declare_function() { .err() .unwrap(); // Make sure this is an error } + +fn define_simple_function(module: &mut Module) -> FuncId { + let sig = Signature { + params: vec![], + returns: vec![], + call_conv: CallConv::SystemV, + argument_bytes: None, + }; + + let func_id = module + .declare_function("abc", Linkage::Local, &sig) + .unwrap(); + + let mut ctx = Context::new(); + ctx.func = Function::with_name_signature(ExternalName::user(0, func_id.index() as u32), sig); + let mut func_ctx = FunctionBuilderContext::new(); + { + let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); + let ebb = bcx.create_ebb(); + bcx.switch_to_block(ebb); + bcx.ins().return_(&[]); + } + + module.define_function(func_id, &mut ctx).unwrap(); + + func_id +} + +#[test] +#[should_panic(expected = "function can't be finalized twice")] +fn panic_on_double_finalize() { + let mut module: Module = Module::new(SimpleJITBuilder::new()); + + let func_id = define_simple_function(&mut module); + module.finalize_function(func_id); + module.finalize_function(func_id); +} + +#[test] +#[should_panic(expected = "Result::unwrap()` on an `Err` value: DuplicateDefinition(\"abc\")")] +fn panic_on_define_after_finalize() { + let mut module: Module = Module::new(SimpleJITBuilder::new()); + + let func_id = define_simple_function(&mut module); + module.finalize_function(func_id); + define_simple_function(&mut module); +} diff --git a/lib/module/src/module.rs b/lib/module/src/module.rs index 133ad5af9f..223f748107 100644 --- a/lib/module/src/module.rs +++ b/lib/module/src/module.rs @@ -562,6 +562,10 @@ where /// Perform all outstanding relocations on the given function. This requires all `Local` /// and `Export` entities referenced to be defined. + /// + /// # Panics + /// + /// When the function has already been finalized this panics pub fn finalize_function(&mut self, func: FuncId) -> B::FinalizedFunction { let output = { let info = &self.contents.functions[func]; @@ -569,6 +573,7 @@ where info.decl.linkage.is_definable(), "imported function cannot be finalized" ); + assert!(!info.finalized, "function can't be finalized twice"); self.backend.finalize_function( info.compiled .as_ref() @@ -584,6 +589,10 @@ where /// Perform all outstanding relocations on the given data object. This requires all /// `Local` and `Export` entities referenced to be defined. + /// + /// # Panics + /// + /// When the data object has already been finalized this panics pub fn finalize_data(&mut self, data: DataId) -> B::FinalizedData { let output = { let info = &self.contents.data_objects[data]; @@ -591,6 +600,7 @@ where info.decl.linkage.is_definable(), "imported data cannot be finalized" ); + assert!(!info.finalized, "data object can't be finalized twice"); self.backend.finalize_data( info.compiled .as_ref()