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(runtime-fuzzer): Aggregational PR for different fuzzer features and adjustments #3268

Merged
merged 6 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/runtime-fuzzer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ubuntu:22.10
FROM ubuntu:22.04

MAINTAINER GEAR

Expand Down
27 changes: 26 additions & 1 deletion utils/node-loader/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use gear_call_gen::Seed;
use gear_core::ids::{MessageId, ProgramId};
use gear_core_errors::ReplyCode;
use gear_utils::NonEmpty;
use gear_wasm_gen::{EntryPointsSet, StandardGearWasmConfigsBundle};
use gear_wasm_gen::{
EntryPointsSet, ParamType, StandardGearWasmConfigsBundle, SysCallName,
SysCallsInjectionAmounts, SysCallsParamsConfig,
};
use gsdk::metadata::runtime_types::{
gear_common::event::DispatchStatus as GenDispatchStatus,
gear_core::{
Expand Down Expand Up @@ -209,10 +212,32 @@ pub fn get_wasm_gen_config(
seed: Seed,
existing_programs: impl Iterator<Item = ProgramId>,
) -> StandardGearWasmConfigsBundle<ProgramId> {
let initial_pages = 2;
let mut injection_amounts = SysCallsInjectionAmounts::all_once();
injection_amounts.set_multiple(
[
(SysCallName::Leave, 0..=0),
(SysCallName::Panic, 0..=0),
(SysCallName::OomPanic, 0..=0),
(SysCallName::Send, 20..=30),
(SysCallName::Exit, 0..=1),
(SysCallName::Alloc, 5..=10),
(SysCallName::Free, 5..=10),
]
.into_iter(),
);

let mut params_config = SysCallsParamsConfig::default();
params_config.add_rule(ParamType::Alloc, (1..=10).into());
params_config.add_rule(ParamType::Free, (initial_pages..=initial_pages + 25).into());

StandardGearWasmConfigsBundle {
log_info: Some(format!("Gear program seed = '{seed}'")),
existing_addresses: NonEmpty::collect(existing_programs),
entry_points_set: EntryPointsSet::InitHandleHandleReply,
injection_amounts,
params_config,
initial_pages: initial_pages as u32,
..Default::default()
}
}
4 changes: 4 additions & 0 deletions utils/runtime-fuzzer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ version = "0.1.0"
authors.workspace = true
edition.workspace = true

[[bin]]
name = "run_corpus"
path = "bin/run_corpus.rs"

[dependencies]
anyhow.workspace = true
arbitrary.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion utils/runtime-fuzzer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ There are two ways to view coverage:
```bash
# generate `lcov.info` file with coverage
HOST_TARGET=$(rustc -Vv | grep "host: " | sed "s/^host: \(.*\)$/\1/")
cargo cov -- export target/x86_64-unknown-linux-gnu/coverage/x86_64-unknown-linux-gnu/release/main \
cargo cov -- export target/$HOST_TARGET/coverage/$HOST_TARGET/release/main \
--format=lcov \
--instr-profile=fuzz/coverage/main/coverage.profdata \
--ignore-filename-regex=/rustc/ \
Expand Down
58 changes: 58 additions & 0 deletions utils/runtime-fuzzer/bin/run_corpus.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// This file is part of Gear.

// Copyright (C) 2021-2023 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Runs provided from the cli corpus
//!
//! Alternatively, `cargo fuzz run` can be used to reproduce some corpus,
//! but it won't give logs of [`GearCalls`] generation, which sheds some
//! light on how `gear-wasm-gen` worked.
//!
//! Also that script can be used to run any bytes input, not only fuzzer's
//! corpus.
//!
//! Just simply run `cargo run --release -- -p <path_to_corpus>`.

use anyhow::Result;
use arbitrary::{Arbitrary, Unstructured};
use clap::Parser;
use runtime_fuzzer::{self, GearCalls};
use std::{fs, path::PathBuf};

/// A simple tool to run corpus.
#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
struct Params {
/// Path to the file, which contains corpus.
#[arg(short, long)]
path: PathBuf,
}

fn main() -> Result<()> {
let params = Params::parse();

let corpus_bytes = fs::read(params.path)?;

gear_utils::init_default_logger();

let mut unstructured = Unstructured::new(&corpus_bytes);
let gear_calls = GearCalls::arbitrary(&mut unstructured)?;

runtime_fuzzer::run(gear_calls);

Ok(())
}
30 changes: 24 additions & 6 deletions utils/runtime-fuzzer/src/arbitrary_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ use arbitrary::{Arbitrary, Result, Unstructured};
use gear_core::ids::{CodeId, ProgramId};
use gear_utils::NonEmpty;
use gear_wasm_gen::{
EntryPointsSet, StandardGearWasmConfigsBundle, SysCallName, SysCallsInjectionAmounts,
EntryPointsSet, ParamType, StandardGearWasmConfigsBundle, SysCallName,
SysCallsInjectionAmounts, SysCallsParamsConfig,
};
use sha1::*;
use std::{
Expand Down Expand Up @@ -190,12 +191,27 @@ fn config(
programs: [ProgramId; GearCalls::INIT_MSGS],
log_info: Option<String>,
) -> StandardGearWasmConfigsBundle<ProgramId> {
let initial_pages = 2;
let mut injection_amounts = SysCallsInjectionAmounts::all_once();
injection_amounts.set(SysCallName::Leave, 0, 0);
injection_amounts.set(SysCallName::Panic, 0, 0);
injection_amounts.set(SysCallName::OomPanic, 0, 0);
injection_amounts.set(SysCallName::Send, 20, 30);
injection_amounts.set(SysCallName::Exit, 0, 1);
injection_amounts.set_multiple(
[
(SysCallName::Leave, 0..=0),
(SysCallName::Panic, 0..=0),
(SysCallName::OomPanic, 0..=0),
(SysCallName::Send, 20..=30),
(SysCallName::Exit, 0..=1),
(SysCallName::Alloc, 20..=30),
(SysCallName::Free, 20..=30),
]
.into_iter(),
);

let mut params_config = SysCallsParamsConfig::default();
params_config.add_rule(ParamType::Alloc, (10..=20).into());
params_config.add_rule(
ParamType::Free,
(initial_pages..=initial_pages + 250).into(),
);

let existing_addresses = NonEmpty::collect(
programs
Expand All @@ -214,6 +230,8 @@ fn config(
injection_amounts,
existing_addresses,
log_info,
params_config,
initial_pages: initial_pages as u32,
..Default::default()
}
}
Expand Down
20 changes: 20 additions & 0 deletions utils/wasm-gen/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ pub struct StandardGearWasmConfigsBundle<T = [u8; 32]> {
pub injection_amounts: SysCallsInjectionAmounts,
/// Config of gear wasm call entry-points (exports).
pub entry_points_set: EntryPointsSet,
/// Initial wasm memory pages.
pub initial_pages: u32,
/// Optional stack end pages.
pub stack_end_page: Option<u32>,
/// Sys-calls params config
pub params_config: SysCallsParamsConfig,
}

impl<T> Default for StandardGearWasmConfigsBundle<T> {
Expand All @@ -158,6 +164,9 @@ impl<T> Default for StandardGearWasmConfigsBundle<T> {
call_indirect_enabled: true,
injection_amounts: SysCallsInjectionAmounts::all_once(),
entry_points_set: Default::default(),
initial_pages: DEFAULT_INITIAL_SIZE,
stack_end_page: None,
params_config: SysCallsParamsConfig::default(),
}
}
}
Expand All @@ -171,6 +180,9 @@ impl<T: Into<Hash>> ConfigsBundle for StandardGearWasmConfigsBundle<T> {
call_indirect_enabled,
injection_amounts,
entry_points_set,
initial_pages,
stack_end_page,
params_config,
} = self;

let selectable_params = SelectableParams {
Expand All @@ -188,10 +200,18 @@ impl<T: Into<Hash>> ConfigsBundle for StandardGearWasmConfigsBundle<T> {
} else {
sys_calls_config_builder = sys_calls_config_builder.with_source_msg_dest();
}
sys_calls_config_builder = sys_calls_config_builder.with_params_config(params_config);

let memory_pages_config = MemoryPagesConfig {
initial_size: initial_pages,
stack_end_page,
upper_limit: None,
};
let gear_wasm_generator_config = GearWasmGeneratorConfigBuilder::new()
.with_recursions_removed(remove_recursion)
.with_sys_calls_config(sys_calls_config_builder.build())
.with_entry_points_config(entry_points_set)
.with_memory_config(memory_pages_config)
.build();

(gear_wasm_generator_config, selectable_params)
Expand Down
6 changes: 4 additions & 2 deletions utils/wasm-gen/src/config/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

use crate::SysCallsConfig;

pub(crate) const DEFAULT_INITIAL_SIZE: u32 = 16;

/// Builder for [`GearWasmGeneratorConfig`].
pub struct GearWasmGeneratorConfigBuilder(GearWasmGeneratorConfig);

Expand Down Expand Up @@ -95,9 +97,9 @@ pub struct MemoryPagesConfig {
impl Default for MemoryPagesConfig {
fn default() -> Self {
Self {
initial_size: Self::MAX_VALUE / 2 + 5,
initial_size: DEFAULT_INITIAL_SIZE,
upper_limit: None,
stack_end_page: Some(Self::MAX_VALUE / 2),
stack_end_page: None,
}
}
}
Expand Down
42 changes: 21 additions & 21 deletions utils/wasm-gen/src/config/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl SysCallsConfigBuilder {
Self(SysCallsConfig {
injection_amounts,
params_config: SysCallsParamsConfig::default(),
sending_message_destination: MessageDestination::default(),
sys_call_destination: SysCallDestination::default(),
error_processing_config: ErrorProcessingConfig::None,
log_info: None,
})
Expand All @@ -54,23 +54,23 @@ impl SysCallsConfigBuilder {
self
}

/// Set whether `gr_send*` sys-calls must use `gr_source` result for message destination.
/// 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.sending_message_destination = MessageDestination::Source;
self.0.sys_call_destination = SysCallDestination::Source;
self.enable_sys_call(SysCallName::Source);

self
}

/// Set whether `gr_send*` sys-calls must use some address from `addresses` collection
/// as a message destination.
/// Set whether `gr_send*` and `gr_exit` sys-calls must use some address from `addresses` collection
/// as a sys-call destination.
pub fn with_data_offset_msg_dest<T: Into<Hash>>(mut self, addresses: NonEmpty<T>) -> Self {
let addresses = NonEmpty::collect(addresses.into_iter().map(|pid| HashWithValue {
hash: pid.into(),
value: 0,
}))
.expect("collected from non empty");
self.0.sending_message_destination = MessageDestination::ExistingAddresses(addresses);
self.0.sys_call_destination = SysCallDestination::ExistingAddresses(addresses);

self
}
Expand Down Expand Up @@ -138,7 +138,7 @@ impl ErrorProcessingConfig {
pub struct SysCallsConfig {
injection_amounts: SysCallsInjectionAmounts,
params_config: SysCallsParamsConfig,
sending_message_destination: MessageDestination,
sys_call_destination: SysCallDestination,
error_processing_config: ErrorProcessingConfig,
log_info: Option<String>,
}
Expand All @@ -149,11 +149,11 @@ impl SysCallsConfig {
self.injection_amounts.get(name)
}

/// Get defined message destination for `gr_send*` sys-calls.
/// Get defined sys-call destination for `gr_send*` and `gr_exit` sys-calls.
///
/// For more info, read [`MessageDestination`].
pub fn sending_message_destination(&self) -> &MessageDestination {
&self.sending_message_destination
/// For more info, read [`SysCallDestination`].
pub fn sys_call_destination(&self) -> &SysCallDestination {
&self.sys_call_destination
}

/// Get defined log info.
Expand All @@ -174,33 +174,33 @@ impl SysCallsConfig {
}
}

/// Message destination choice.
/// Sys-call destination choice.
///
/// `gr_send*` sys-calls generated from this crate can send messages
/// `gr_send*` and `gr_exit` sys-calls generated from this crate can be sent
/// to different destination in accordance to the config.
/// It's either to the message source, to some existing known address,
/// or to some random, most probably non-existing, address.
#[derive(Debug, Clone, Default)]
pub enum MessageDestination {
pub enum SysCallDestination {
Source,
ExistingAddresses(NonEmpty<HashWithValue>),
#[default]
Random,
}

impl MessageDestination {
/// Check whether message destination is a result of `gr_source`.
impl SysCallDestination {
/// Check whether sys-call destination is a result of `gr_source`.
pub fn is_source(&self) -> bool {
matches!(&self, MessageDestination::Source)
matches!(&self, SysCallDestination::Source)
}

/// Check whether message destination is defined randomly.
/// Check whether sys-call destination is defined randomly.
pub fn is_random(&self) -> bool {
matches!(&self, MessageDestination::Random)
matches!(&self, SysCallDestination::Random)
}

/// Check whether message destination is defined from a collection of existing addresses.
/// Check whether sys-call destination is defined from a collection of existing addresses.
pub fn is_existing_addresses(&self) -> bool {
matches!(&self, MessageDestination::ExistingAddresses(_))
matches!(&self, SysCallDestination::ExistingAddresses(_))
}
}
Loading
Loading