Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(wasm-gen): create config for precise sys-calls #3262

Merged
merged 12 commits into from
Sep 18, 2023
Merged
3 changes: 2 additions & 1 deletion utils/runtime-fuzzer/src/arbitrary_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use arbitrary::{Arbitrary, Result, Unstructured};
use gear_core::ids::{CodeId, ProgramId};
use gear_utils::NonEmpty;
use gear_wasm_gen::{
EntryPointsSet, ParamType, StandardGearWasmConfigsBundle, SysCallName,
EntryPointsSet, InvocableSysCall, ParamType, StandardGearWasmConfigsBundle, SysCallName,
SysCallsInjectionAmounts, SysCallsParamsConfig,
};
use sha1::*;
Expand Down Expand Up @@ -203,6 +203,7 @@ fn config(
(SysCallName::Alloc, 20..=30),
(SysCallName::Free, 20..=30),
]
.map(|(sys_call, range)| (InvocableSysCall::Loose(sys_call), range))
.into_iter(),
);

Expand Down
8 changes: 4 additions & 4 deletions utils/wasm-gen/src/config/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl SysCallsConfigBuilder {
/// Set whether `gr_send*` and `gr_exit` sys-calls must use `gr_source` result for sys-call destination.
pub fn with_source_msg_dest(mut self) -> Self {
self.0.sys_call_destination = SysCallDestination::Source;
self.enable_sys_call(SysCallName::Source);
self.enable_sys_call(InvocableSysCall::Loose(SysCallName::Source));

self
}
Expand All @@ -81,7 +81,7 @@ impl SysCallsConfigBuilder {
/// Choosing gear export to log data is done from best `init` to worse `handle`.
pub fn with_log_info(mut self, log: String) -> Self {
self.0.log_info = Some(log);
self.enable_sys_call(SysCallName::Debug);
self.enable_sys_call(InvocableSysCall::Loose(SysCallName::Debug));

self
}
Expand All @@ -93,7 +93,7 @@ impl SysCallsConfigBuilder {
self
}

fn enable_sys_call(&mut self, name: SysCallName) {
fn enable_sys_call(&mut self, name: InvocableSysCall) {
let range = self.0.injection_amounts.get(name);

let range_start = *range.start();
Expand Down Expand Up @@ -145,7 +145,7 @@ pub struct SysCallsConfig {

impl SysCallsConfig {
/// Get possible number of times (range) the sys-call can be injected in the wasm.
pub fn injection_amounts(&self, name: SysCallName) -> RangeInclusive<u32> {
pub fn injection_amounts(&self, name: InvocableSysCall) -> RangeInclusive<u32> {
self.injection_amounts.get(name)
}

Expand Down
37 changes: 22 additions & 15 deletions utils/wasm-gen/src/config/syscalls/amount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,51 +20,58 @@
//!
//! Types here are used to create [`crate::SysCallsConfig`].

use crate::InvocableSysCall;

use gear_wasm_instrument::syscalls::SysCallName;
use std::{collections::HashMap, ops::RangeInclusive};

/// Possible injection amount ranges for each sys-call.
#[derive(Debug, Clone)]
pub struct SysCallsInjectionAmounts(HashMap<SysCallName, RangeInclusive<u32>>);
pub struct SysCallsInjectionAmounts(HashMap<InvocableSysCall, RangeInclusive<u32>>);

impl SysCallsInjectionAmounts {
/// Instantiate a sys-calls amounts ranges map, where each gear sys-call is injected into wasm-module only once.
pub fn all_once() -> Self {
fn new_with_range(range: RangeInclusive<u32>) -> Self {
StackOverflowExcept1on marked this conversation as resolved.
Show resolved Hide resolved
let sys_calls = SysCallName::instrumentable();
Self(
SysCallName::instrumentable()
.into_iter()
.map(|name| (name, (1..=1)))
sys_calls
.iter()
.cloned()
.map(|name| (InvocableSysCall::Loose(name), range.clone()))
.chain(sys_calls.iter().cloned().filter_map(|name| {
InvocableSysCall::has_precise_variant(name)
.then_some((InvocableSysCall::Precise(name), range.clone()))
}))
.collect(),
)
}

/// Instantiate a sys-calls amounts ranges map, where each gear sys-call is injected into wasm-module only once.
pub fn all_once() -> Self {
Self::new_with_range(1..=1)
}

/// Instantiate a sys-calls amounts ranges map, where no gear sys-call is ever injected into wasm-module.
pub fn all_never() -> Self {
Self(
SysCallName::instrumentable()
.into_iter()
.map(|name| (name, (0..=0)))
.collect(),
)
Self::new_with_range(0..=0)
}

/// Get amount possible sys-call amount range.
pub fn get(&self, name: SysCallName) -> RangeInclusive<u32> {
pub fn get(&self, name: InvocableSysCall) -> RangeInclusive<u32> {
self.0
.get(&name)
.cloned()
.expect("instantiated with all sys-calls set")
}

/// Sets possible amount range for the the sys-call.
pub fn set(&mut self, name: SysCallName, min: u32, max: u32) {
pub fn set(&mut self, name: InvocableSysCall, min: u32, max: u32) {
self.0.insert(name, min..=max);
}

/// Same as [`SysCallsAmountRanges::set`], but sets amount ranges for multiple sys-calls.
pub fn set_multiple(
&mut self,
sys_calls_freqs: impl Iterator<Item = (SysCallName, RangeInclusive<u32>)>,
sys_calls_freqs: impl Iterator<Item = (InvocableSysCall, RangeInclusive<u32>)>,
) {
self.0.extend(sys_calls_freqs)
}
Expand Down
10 changes: 10 additions & 0 deletions utils/wasm-gen/src/generator/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ impl InvocableSysCall {
}
}

pub(crate) fn has_precise_variant(sys_call: SysCallName) -> bool {
matches!(
sys_call,
SysCallName::ReservationSend
| SysCallName::ReservationReply
| SysCallName::SendCommit
| SysCallName::SendCommitWGas
)
}

// If syscall changes from fallible into infallible or vice versa in future,
// we'll see it by analyzing code coverage stats produced by fuzzer.
pub(crate) fn is_fallible(&self) -> bool {
Expand Down
4 changes: 3 additions & 1 deletion utils/wasm-gen/src/generator/syscalls/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@ impl<'a, 'b> SysCallsImportsGenerator<'a, 'b> {
&mut self,
sys_call: SysCallName,
) -> Result<Option<(u32, CallIndexesHandle)>> {
let sys_call_amount_range = self.config.injection_amounts(sys_call);
let sys_call_amount_range = self
.config
.injection_amounts(InvocableSysCall::Loose(sys_call));
let sys_call_amount = self.unstructured.int_in_range(sys_call_amount_range)?;
Ok((sys_call_amount != 0).then(|| {
let call_indexes_handle = self.insert_sys_call_import(sys_call);
Expand Down
6 changes: 5 additions & 1 deletion utils/wasm-gen/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,11 @@ fn execute_wasm_with_syscall_injected(
let mut unstructured = Unstructured::new(&buf);

let mut injection_amounts = SysCallsInjectionAmounts::all_never();
injection_amounts.set(syscall, INJECTED_SYSCALLS, INJECTED_SYSCALLS);
injection_amounts.set(
InvocableSysCall::Loose(syscall),
INJECTED_SYSCALLS,
INJECTED_SYSCALLS,
);

let error_processing_config = if ignore_fallible_errors {
ErrorProcessingConfig::None
Expand Down