///|
fn gen_valid_campaign_segment_state_config() -> GenValidConfig {
let base = GenValidConfig::binaryen_oracle_coverage_forced_default()
GenValidConfig::{
..base,
max_type_defs: 1,
max_imports: 0,
max_defined_funcs: 2,
max_tables: 1,
max_mems: 1,
max_globals: 0,
max_tags: 0,
max_elems: 5,
max_datas: 4,
max_params: 0,
max_results: 0,
max_locals: 0,
max_body_statements: 274,
max_body_depth: 1,
max_segment_payload_size: 24,
features: GenValidFeatureToggles::{
..base.features,
allow_imports: false,
allow_tables: true,
allow_mems: true,
allow_globals: false,
allow_tags: false,
allow_elems: true,
allow_datas: true,
allow_ref_types: true,
allow_memory64: false,
allow_atomics: false,
allow_shared_memories: false,
allow_name_custom_sections: false,
allow_typed_body_generator: false,
allow_ssa_nomerge_body_generator: false,
},
}
}
///|
fn gen_valid_campaign_segment_state_bytes(seed : UInt64, salt : Int32) -> Bytes {
let bytes : Array[Byte] = []
let length = 5 + ((seed + salt.to_uint64() * 11UL) % 7UL).to_int()
for offset = 0; offset < length; offset = offset + 1 {
bytes.push(
((seed + salt.to_uint64() * 37UL + offset.to_uint64() * 13UL) & 0xffUL).to_byte(),
)
}
Bytes::from_array(bytes)
}
///|
fn gen_valid_campaign_segment_state_module(ctx : GenValidContext) -> Module {
let seed = ctx.root_seed
let data_rotation = (seed % 4UL).to_int()
let swap_passive_elems = ((seed >> 2) & 1UL) != 0UL
let swap_active_elems = ((seed >> 3) & 1UL) != 0UL
let data_offset = 8 + ((seed * 7UL + 3UL) % 9UL).to_int()
let elem_offset = 1 + (seed / 3UL % 2UL).to_int()
let datas : Array[Data] = []
let elems : Array[Elem] = []
let mut active_data = 0U
let mut first_passive_data = 0U
let mut second_passive_data = 0U
let mut first_passive_elem = 0U
let mut second_passive_elem = 0U
for slot = 0; slot < 4; slot = slot + 1 {
let category = (slot + data_rotation) % 4
let mode = if category == 0 || category == 2 {
if category == 0 {
active_data = slot.to_uint()
}
DataMode::active(
MemIdx::new(0U),
Expr::new([
Instruction::i32_const(
I32(if category == 0 { data_offset } else { data_offset + 3 }),
),
]),
)
} else {
if category == 1 {
first_passive_data = slot.to_uint()
} else {
second_passive_data = slot.to_uint()
}
DataMode::passive()
}
datas.push(
Data::new(mode, gen_valid_campaign_segment_state_bytes(seed, category)),
)
}
for slot = 0; slot < 5; slot = slot + 1 {
// Binaryen 132 addresses passive segments by their passive-only index.
// Keep them first so its parser accepts both bulk-operation targets.
let category = match slot {
0 => if swap_passive_elems { 4 } else { 1 }
1 => if swap_passive_elems { 1 } else { 4 }
2 => if swap_active_elems { 3 } else { 0 }
3 => if swap_active_elems { 0 } else { 3 }
_ => 2
}
let mode = match category {
0 | 3 =>
ElemMode::active(
TableIdx::new(0U),
Expr::new([
Instruction::i32_const(
I32(if category == 0 { elem_offset } else { elem_offset + 1 }),
),
]),
)
1 | 4 => {
if category == 1 {
first_passive_elem = slot.to_uint()
} else {
second_passive_elem = slot.to_uint()
}
ElemMode::passive()
}
_ => ElemMode::declarative()
}
elems.push(
Elem::new(
mode,
ElemKind::funcs(
if category == 0 || category == 3 {
[FuncIdx::new(0U), FuncIdx::new(1U)]
} else {
[FuncIdx::new((seed % 2UL).to_uint())]
},
),
),
)
}
let run : Array[Instruction] = [
Instruction::i32_const(I32(32 + (seed * 5UL % 16UL).to_int())),
Instruction::i32_const(I32(1)),
Instruction::i32_const(I32(2)),
Instruction::memory_init(DataIdx::new(first_passive_data), MemIdx::new(0U)),
Instruction::data_drop(DataIdx::new(first_passive_data)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::memory_init(DataIdx::new(first_passive_data), MemIdx::new(0U)),
Instruction::i32_const(I32(48)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(1)),
Instruction::memory_init(DataIdx::new(second_passive_data), MemIdx::new(0U)),
Instruction::data_drop(DataIdx::new(second_passive_data)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(1)),
Instruction::table_init(ElemIdx::new(first_passive_elem), TableIdx::new(0U)),
Instruction::elem_drop(ElemIdx::new(first_passive_elem)),
Instruction::i32_const(I32(1)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(1)),
Instruction::table_init(
ElemIdx::new(second_passive_elem),
TableIdx::new(0U),
),
Instruction::elem_drop(ElemIdx::new(second_passive_elem)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::memory_init(DataIdx::new(active_data), MemIdx::new(0U)),
Instruction::data_drop(DataIdx::new(active_data)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::table_init(ElemIdx::new(first_passive_elem), TableIdx::new(0U)),
Instruction::elem_drop(ElemIdx::new(second_passive_elem)),
]
let probe : Array[Instruction] = []
if (seed & 1UL) == 0UL {
probe.append([
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(1)),
Instruction::memory_init(DataIdx::new(active_data), MemIdx::new(0U)),
])
} else {
probe.append([
Instruction::elem_drop(ElemIdx::new(first_passive_elem)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(1)),
Instruction::table_init(
ElemIdx::new(first_passive_elem),
TableIdx::new(0U),
),
])
}
Module::new()
.with_type_sec(
TypeSec::new([RecType::new(SubType::comp_type(CompType::func([], [])))]),
)
.with_func_sec(FuncSec::new([TypeIdx::new(0U), TypeIdx::new(0U)]))
.with_table_sec(
TableSec::new([
Table::new(
TableType::new(
RefType::abs(AbsHeapType::func()),
Limits::i32(8U, Some(8U)),
),
None,
),
]),
)
.with_mem_sec(MemSec::new([MemType::new(Limits::i32(1U, Some(1U)))]))
.with_elem_sec(ElemSec::new(elems))
.with_data_cnt_sec(DataCntSec::new(U32(4U)))
.with_code_sec(
CodeSec::new([
Func::new(Locals::empty(), Expr::new(run)),
Func::new(Locals::empty(), Expr::new(probe)),
]),
)
.with_data_sec(DataSec::new(datas))
.with_export_sec(
ExportSec::new([
Export::new(Name::new("run"), ExternIdx::func(FuncIdx::new(0U))),
Export::new(Name::new("probe"), ExternIdx::func(FuncIdx::new(1U))),
]),
)
}