mirror of
https://github.com/pezkuwichain/wasm-instrument.git
synced 2026-06-13 21:01:07 +00:00
Patch: use checked sum for locals counter (#40)
follow-up patch to #38 Co-authored-by: Alexander Theißen <alex.theissen@me.com>
This commit is contained in:
@@ -112,8 +112,8 @@ pub mod mutable_global {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// calculate gas used for the gas charging func execution itself
|
// calculate gas used for the gas charging func execution itself
|
||||||
let mut gas_fn_cost = func_instructions.iter().fold(0, |cost, instruction| {
|
let mut gas_fn_cost = func_instructions.iter().fold(0, |cost: u64, instruction| {
|
||||||
cost + (rules.instruction_cost(instruction).unwrap_or(0) as u64)
|
cost.saturating_add(rules.instruction_cost(instruction).unwrap_or(u32::MAX).into())
|
||||||
});
|
});
|
||||||
// don't charge for the instructions used to fail when out of gas
|
// don't charge for the instructions used to fail when out of gas
|
||||||
let fail_cost = vec![
|
let fail_cost = vec![
|
||||||
@@ -122,10 +122,11 @@ pub mod mutable_global {
|
|||||||
Instruction::Unreachable, // non-charged instruction
|
Instruction::Unreachable, // non-charged instruction
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.fold(0, |cost, instruction| {
|
.fold(0, |cost: u64, instruction| {
|
||||||
cost + (rules.instruction_cost(instruction).unwrap_or(0) as u64)
|
cost.saturating_add(rules.instruction_cost(instruction).unwrap_or(u32::MAX).into())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// the fail costs are a subset of the overall costs and hence this never underflows
|
||||||
gas_fn_cost -= fail_cost;
|
gas_fn_cost -= fail_cost;
|
||||||
|
|
||||||
GasMeter::Internal {
|
GasMeter::Internal {
|
||||||
|
|||||||
+23
-23
@@ -166,7 +166,7 @@ pub fn inject<R: Rules, B: Backend>(
|
|||||||
let functions_space = module.functions_space() as u32;
|
let functions_space = module.functions_space() as u32;
|
||||||
let gas_global_idx = module.globals_space() as u32;
|
let gas_global_idx = module.globals_space() as u32;
|
||||||
|
|
||||||
let mut mbuilder = builder::from_module(module);
|
let mut mbuilder = builder::from_module(module.clone());
|
||||||
|
|
||||||
// Calculate the indexes and gas function cost,
|
// Calculate the indexes and gas function cost,
|
||||||
// for external gas function the cost is counted on the host side
|
// for external gas function the cost is counted on the host side
|
||||||
@@ -224,15 +224,14 @@ pub fn inject<R: Rules, B: Backend>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// We need the built the module for making injections to its blocks
|
// We need the built the module for making injections to its blocks
|
||||||
let mut module = mbuilder.build();
|
let mut resulting_module = mbuilder.build();
|
||||||
|
|
||||||
let mut need_grow_counter = false;
|
let mut need_grow_counter = false;
|
||||||
let mut error = false;
|
let mut result = Ok(());
|
||||||
|
|
||||||
// Iterate over module sections and perform needed transformations.
|
// Iterate over module sections and perform needed transformations.
|
||||||
// Indexes are needed to be fixed up in `GasMeter::External` case, as it adds an imported
|
// Indexes are needed to be fixed up in `GasMeter::External` case, as it adds an imported
|
||||||
// function, which goes to the beginning of the module's functions space.
|
// function, which goes to the beginning of the module's functions space.
|
||||||
for section in module.sections_mut() {
|
'outer: for section in resulting_module.sections_mut() {
|
||||||
match section {
|
match section {
|
||||||
elements::Section::Code(code_section) => {
|
elements::Section::Code(code_section) => {
|
||||||
let injection_targets = match gas_meter {
|
let injection_targets = match gas_meter {
|
||||||
@@ -257,19 +256,22 @@ pub fn inject<R: Rules, B: Backend>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let locals_count =
|
result = func_body
|
||||||
func_body.locals().iter().map(|val_type| val_type.count()).sum();
|
.locals()
|
||||||
if inject_counter(
|
.iter()
|
||||||
func_body.code_mut(),
|
.try_fold(0u32, |count, val_type| count.checked_add(val_type.count()))
|
||||||
gas_fn_cost,
|
.ok_or(())
|
||||||
locals_count,
|
.and_then(|locals_count| {
|
||||||
rules,
|
inject_counter(
|
||||||
gas_func_idx,
|
func_body.code_mut(),
|
||||||
)
|
gas_fn_cost,
|
||||||
.is_err()
|
locals_count,
|
||||||
{
|
rules,
|
||||||
error = true;
|
gas_func_idx,
|
||||||
break
|
)
|
||||||
|
});
|
||||||
|
if result.is_err() {
|
||||||
|
break 'outer
|
||||||
}
|
}
|
||||||
if rules.memory_grow_cost().enabled() &&
|
if rules.memory_grow_cost().enabled() &&
|
||||||
inject_grow_counter(func_body.code_mut(), total_func) > 0
|
inject_grow_counter(func_body.code_mut(), total_func) > 0
|
||||||
@@ -325,14 +327,12 @@ pub fn inject<R: Rules, B: Backend>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if error {
|
result.map_err(|_| module)?;
|
||||||
return Err(module)
|
|
||||||
}
|
|
||||||
|
|
||||||
if need_grow_counter {
|
if need_grow_counter {
|
||||||
Ok(add_grow_counter(module, rules, gas_func_idx))
|
Ok(add_grow_counter(resulting_module, rules, gas_func_idx))
|
||||||
} else {
|
} else {
|
||||||
Ok(module)
|
Ok(resulting_module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,8 +135,12 @@ fn build_control_flow_graph(
|
|||||||
let mut stack = vec![ControlFrame::new(entry_node_id, terminal_node_id, false)];
|
let mut stack = vec![ControlFrame::new(entry_node_id, terminal_node_id, false)];
|
||||||
let mut metered_blocks_iter = blocks.iter().peekable();
|
let mut metered_blocks_iter = blocks.iter().peekable();
|
||||||
|
|
||||||
let locals_count = body.locals().iter().fold(0, |count, val_type| count + val_type.count());
|
let locals_count = body
|
||||||
let locals_init_cost = (rules.call_per_local_cost()).checked_mul(locals_count).ok_or(())?;
|
.locals()
|
||||||
|
.iter()
|
||||||
|
.try_fold(0u32, |count, val_type| count.checked_add(val_type.count()))
|
||||||
|
.ok_or(())?;
|
||||||
|
let locals_init_cost = rules.call_per_local_cost().checked_mul(locals_count).ok_or(())?;
|
||||||
|
|
||||||
for (cursor, instruction) in body.code().elements().iter().enumerate() {
|
for (cursor, instruction) in body.code().elements().iter().enumerate() {
|
||||||
let active_node_id = stack
|
let active_node_id = stack
|
||||||
@@ -350,8 +354,7 @@ mod tests {
|
|||||||
|
|
||||||
for func_body in module.code_section().iter().flat_map(|section| section.bodies()) {
|
for func_body in module.code_section().iter().flat_map(|section| section.bodies()) {
|
||||||
let rules = ConstantCostRules::default();
|
let rules = ConstantCostRules::default();
|
||||||
let locals_count =
|
let locals_count = func_body.locals().iter().map(|val_type| val_type.count()).sum();
|
||||||
func_body.locals().iter().fold(0, |count, val_type| count + val_type.count());
|
|
||||||
|
|
||||||
let metered_blocks =
|
let metered_blocks =
|
||||||
determine_metered_blocks(func_body.code(), &rules, locals_count).unwrap();
|
determine_metered_blocks(func_body.code(), &rules, locals_count).unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user