diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/METER_TESTING.md b/language/move-bytecode-verifier/bytecode-verifier-tests/METER_TESTING.md new file mode 100644 index 0000000000..cd5ae0f421 --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/METER_TESTING.md @@ -0,0 +1,5 @@ +This testsuite can be run in a specific way to print the time until a 'complex' program is detected or accepted. Call as in: + +``` +cargo test --release --features=address32 -- --nocapture 1>/dev/null +``` diff --git a/language/move-bytecode-verifier/src/absint.rs b/language/move-bytecode-verifier/src/absint.rs index d64a4212db..9945d6f3d7 100644 --- a/language/move-bytecode-verifier/src/absint.rs +++ b/language/move-bytecode-verifier/src/absint.rs @@ -6,6 +6,7 @@ use crate::meter::Meter; use move_binary_format::{ binary_views::FunctionView, control_flow_graph::{BlockId, ControlFlowGraph}, + errors::PartialVMResult, file_format::{Bytecode, CodeOffset}, }; use std::collections::BTreeMap; @@ -56,7 +57,7 @@ pub trait TransferFunctions { index: CodeOffset, last_index: CodeOffset, meter: &mut impl Meter, - ) -> Result<(), Self::Error>; + ) -> PartialVMResult<()>; } pub trait AbstractInterpreter: TransferFunctions { @@ -66,7 +67,7 @@ pub trait AbstractInterpreter: TransferFunctions { initial_state: Self::State, function_view: &FunctionView, meter: &mut impl Meter, - ) -> Result<(), Self::Error> { + ) -> PartialVMResult<()> { let mut inv_map = InvariantMap::new(); let entry_block_id = function_view.cfg().entry_block_id(); let mut next_block = Some(entry_block_id); @@ -137,7 +138,7 @@ pub trait AbstractInterpreter: TransferFunctions { pre_state: &Self::State, function_view: &FunctionView, meter: &mut impl Meter, - ) -> Result { + ) -> PartialVMResult { let mut state_acc = pre_state.clone(); let block_end = function_view.cfg().block_end(block_id); for offset in function_view.cfg().instr_indexes(block_id) { diff --git a/language/move-bytecode-verifier/src/type_safety.rs b/language/move-bytecode-verifier/src/type_safety.rs index 75dda8c50a..ee0f95b739 100644 --- a/language/move-bytecode-verifier/src/type_safety.rs +++ b/language/move-bytecode-verifier/src/type_safety.rs @@ -83,12 +83,27 @@ impl<'a> TypeSafetyChecker<'a> { } fn push(&mut self, meter: &mut impl Meter, ty: SignatureToken) -> PartialVMResult<()> { + self.charge_ty(meter, &ty)?; + self.stack.push(ty); + Ok(()) + } + + fn charge_ty(&mut self, meter: &mut impl Meter, ty: &SignatureToken) -> PartialVMResult<()> { meter.add_items( Scope::Function, TYPE_NODE_COST, ty.preorder_traversal().count(), - )?; - self.stack.push(ty); + ) + } + + fn charge_tys( + &mut self, + meter: &mut impl Meter, + tys: &[SignatureToken], + ) -> PartialVMResult<()> { + for ty in tys { + self.charge_ty(meter, ty)? + } Ok(()) } } @@ -96,7 +111,7 @@ impl<'a> TypeSafetyChecker<'a> { pub(crate) fn verify<'a>( resolver: &'a BinaryIndexedView<'a>, function_view: &'a FunctionView<'a>, - meter: &mut impl Meter, // currently unused + meter: &mut impl Meter, ) -> PartialVMResult<()> { let verifier = &mut TypeSafetyChecker::new(resolver, function_view); @@ -481,6 +496,7 @@ fn verify_instr( .resolver .field_instantiation_at(*field_inst_index)?; let type_inst = verifier.resolver.signature_at(field_inst.type_parameters); + verifier.charge_tys(meter, &type_inst.0)?; borrow_field(verifier, meter, offset, true, field_inst.handle, type_inst)? } @@ -498,6 +514,7 @@ fn verify_instr( .resolver .field_instantiation_at(*field_inst_index)?; let type_inst = verifier.resolver.signature_at(field_inst.type_parameters); + verifier.charge_tys(meter, &type_inst.0)?; borrow_field(verifier, meter, offset, false, field_inst.handle, type_inst)? } @@ -564,6 +581,7 @@ fn verify_instr( let func_inst = verifier.resolver.function_instantiation_at(*idx); let func_handle = verifier.resolver.function_handle_at(func_inst.handle); let type_args = &verifier.resolver.signature_at(func_inst.type_parameters); + verifier.charge_tys(meter, &type_args.0)?; call(verifier, meter, offset, func_handle, type_args)? } @@ -582,6 +600,7 @@ fn verify_instr( let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let struct_def = verifier.resolver.struct_def_at(struct_inst.def)?; let type_args = verifier.resolver.signature_at(struct_inst.type_parameters); + verifier.charge_tys(meter, &type_args.0)?; pack(verifier, meter, offset, struct_def, type_args)? } @@ -600,6 +619,7 @@ fn verify_instr( let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let struct_def = verifier.resolver.struct_def_at(struct_inst.def)?; let type_args = verifier.resolver.signature_at(struct_inst.type_parameters); + verifier.charge_tys(meter, &type_args.0)?; unpack(verifier, meter, offset, struct_def, type_args)? } @@ -733,6 +753,7 @@ fn verify_instr( Bytecode::MutBorrowGlobalGeneric(idx) => { let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let type_inst = verifier.resolver.signature_at(struct_inst.type_parameters); + verifier.charge_tys(meter, &type_inst.0)?; borrow_global(verifier, meter, offset, true, struct_inst.def, type_inst)? } @@ -743,6 +764,7 @@ fn verify_instr( Bytecode::ImmBorrowGlobalGeneric(idx) => { let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let type_inst = verifier.resolver.signature_at(struct_inst.type_parameters); + verifier.charge_tys(meter, &type_inst.0)?; borrow_global(verifier, meter, offset, false, struct_inst.def, type_inst)? } @@ -755,6 +777,7 @@ fn verify_instr( let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let struct_def = verifier.resolver.struct_def_at(struct_inst.def)?; let type_args = verifier.resolver.signature_at(struct_inst.type_parameters); + verifier.charge_tys(meter, &type_args.0)?; exists(verifier, meter, offset, struct_def, type_args)? } @@ -767,6 +790,7 @@ fn verify_instr( let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let struct_def = verifier.resolver.struct_def_at(struct_inst.def)?; let type_args = verifier.resolver.signature_at(struct_inst.type_parameters); + verifier.charge_tys(meter, &type_args.0)?; move_from(verifier, meter, offset, struct_def, type_args)? } @@ -779,6 +803,7 @@ fn verify_instr( let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let struct_def = verifier.resolver.struct_def_at(struct_inst.def)?; let type_args = verifier.resolver.signature_at(struct_inst.type_parameters); + verifier.charge_tys(meter, &type_args.0)?; move_to(verifier, offset, struct_def, type_args)? } diff --git a/language/move-compiler/src/expansion/ast.rs b/language/move-compiler/src/expansion/ast.rs index 8ce89ea01c..7b73e17cc9 100644 --- a/language/move-compiler/src/expansion/ast.rs +++ b/language/move-compiler/src/expansion/ast.rs @@ -36,7 +36,6 @@ pub struct Program { //************************************************************************************************** #[derive(Debug, Clone, PartialEq, Eq)] -#[allow(clippy::large_enum_variant)] pub enum AttributeValue_ { Value(Value), Module(ModuleIdent),