Skip to content

Commit

Permalink
feat(runtime-fuzzer): use previously waited message id as wake syscal…
Browse files Browse the repository at this point in the history
…l param (#4076)
  • Loading branch information
ByteNacked authored Jul 26, 2024
1 parent 9cdc3d0 commit d954e57
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 90 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion utils/runtime-fuzzer/src/generator/upload_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ fn config(
actor_kind: actor_kind.clone(),
range: EXISTENTIAL_DEPOSIT..=max_value,
})
.with_ptr_rule(PtrParamAllowedValues::ReservationId);
.with_ptr_rule(PtrParamAllowedValues::ReservationId)
.with_ptr_rule(PtrParamAllowedValues::WaitedMessageId);

if let Some(code_ids) = code_ids {
params_config = params_config.with_ptr_rule(PtrParamAllowedValues::CodeIdsWithValue {
Expand Down
1 change: 1 addition & 0 deletions utils/wasm-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ gear-core.workspace = true
wasmparser.workspace = true
thiserror.workspace = true
indexmap.workspace = true
nonempty.workspace = true

[dev-dependencies]
rand = { workspace = true, features = ["small_rng"] }
Expand Down
4 changes: 4 additions & 0 deletions utils/wasm-gen/src/config/syscalls/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ impl SyscallsParamsConfig {
range,
})
.with_ptr_rule(PtrParamAllowedValues::ReservationId)
.with_ptr_rule(PtrParamAllowedValues::WaitedMessageId)
}

/// Set rules for a regular syscall param.
Expand Down Expand Up @@ -127,6 +128,7 @@ impl SyscallsParamsConfig {
}
PtrParamAllowedValues::ReservationId => Ptr::Hash(HashType::ReservationId),
PtrParamAllowedValues::CodeIdsWithValue { .. } => Ptr::HashWithValue(HashType::CodeId),
PtrParamAllowedValues::WaitedMessageId => Ptr::Hash(HashType::MessageId),
};

self.ptr.insert(ptr, allowed_values);
Expand Down Expand Up @@ -272,6 +274,8 @@ pub enum PtrParamAllowedValues {
code_ids: NonEmpty<CodeId>,
range: RangeInclusive<u128>,
},
/// Variant of `Ptr::Hash` pointer type, where hash is waited message id.
WaitedMessageId,
}

/// Actor kind, which is actually a syscall destination choice.
Expand Down
3 changes: 3 additions & 0 deletions utils/wasm-gen/src/generator/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ impl InvocableSyscall {
SyscallName::SendCommitWGas,
],
SyscallName::ReplyDeposit => &[SyscallName::SendInput, SyscallName::ReplyDeposit],
// Enable `MessageId` syscall import if `Wake` syscall is enabled.
// This is done to provide a syscall `Wake` with a correct message id.
SyscallName::Wake => &[SyscallName::MessageId],
_ => return None,
})
}
Expand Down
31 changes: 31 additions & 0 deletions utils/wasm-gen/src/generator/syscalls/invocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> {

match invocable {
Loose(Wait | WaitFor | WaitUpTo) => {
self.store_waited_message_id(&mut instructions);

if let Some(waiting_probability) = self.config.waiting_probability() {
self.limit_infinite_waits(&mut instructions, waiting_probability.get());
}
Expand Down Expand Up @@ -674,6 +676,12 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> {

ret_instr
}
PtrParamAllowedValues::WaitedMessageId => {
// Loads waited message id on previous `Wait`-like syscall.
// Check `SyscallsInvocator::store_waited_message_id` method for implementation details.
let memory_layout = MemoryLayout::from(self.memory_size_bytes());
vec![Instruction::I32Const(memory_layout.waited_message_id_ptr)]
}
};

Ok(ParamInstructions(ret))
Expand Down Expand Up @@ -823,6 +831,29 @@ impl<'a, 'b> SyscallsInvocator<'a, 'b> {
}
}

fn store_waited_message_id(&self, instructions: &mut Vec<Instruction>) {
let Some(gr_message_id_indexes_handle) = self
.syscalls_imports
.get(&InvocableSyscall::Loose(SyscallName::MessageId))
.map(|&(_, call_indexes_handle)| call_indexes_handle as u32)
else {
// We automatically enable the `message_id` syscall import if the `wait` syscall is enabled in the config.
// If not, then we don't need to store the message ID.
return;
};

let memory_layout = MemoryLayout::from(self.memory_size_bytes());
let start_offset = memory_layout.waited_message_id_ptr;

let message_id_call = vec![
// call `gsys::gr_message_id` storing message id at `start_offset` pointer.
Instruction::I32Const(start_offset),
Instruction::Call(gr_message_id_indexes_handle),
];

instructions.splice(0..0, message_id_call);
}

/// Patches instructions of wait-syscalls to prevent deadlocks.
fn limit_infinite_waits(&self, instructions: &mut Vec<Instruction>, waiting_probability: u32) {
let MemoryLayout {
Expand Down
Loading

0 comments on commit d954e57

Please sign in to comment.