Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
13 changes: 11 additions & 2 deletions fuzz/fuzz_targets/fuzz_tx_consistency.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
#![no_main]

use std::sync::atomic::{AtomicUsize, Ordering};
use libfuzzer_sys::fuzz_target;
use schedfuzz::{patch, sched};

static INCONSISTENCY_COUNT: AtomicUsize = AtomicUsize::new(0);

fuzz_target!(|data: &[u8]| {
// Fuzzed code goes here
let r_patch = patch::run(data, 0).map_err(|e| schedfuzz::normalize_error(format!("{:?}", e)));
let r_sched = sched::run(data, 0).map_err(|e| schedfuzz::normalize_error(format!("{:?}", e)));
assert_eq!(r_patch, r_sched);
if r_patch != r_sched {
let count = INCONSISTENCY_COUNT.fetch_add(1, Ordering::Relaxed) + 1;
eprintln!("inconsistency #{count} (version 0): left={r_patch:?}, right={r_sched:?}");
}

let r_patch = patch::run(data, 2).map_err(|e| schedfuzz::normalize_error(format!("{:?}", e)));
let r_sched = sched::run(data, 2).map_err(|e| schedfuzz::normalize_error(format!("{:?}", e)));
assert_eq!(r_patch, r_sched);
if r_patch != r_sched {
let count = INCONSISTENCY_COUNT.fetch_add(1, Ordering::Relaxed) + 1;
eprintln!("inconsistency #{count} (version 2): left={r_patch:?}, right={r_sched:?}");
}
});
10 changes: 6 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,20 +117,22 @@ pub mod patch {

/// Normalize an error string to ignore known formatting differences between
/// CKB VM versions. For example, one version may produce `MemWriteOnExecutablePage`
/// while another produces `MemWriteOnExecutablePage(18)`.
/// while another produces `MemWriteOnExecutablePage(18)`, or `MemOutOfBound`
/// while another produces `MemOutOfBound(4194364, Memory)`.
pub fn normalize_error(err: String) -> String {
let mut result = err;
let patterns = ["MemWriteOnExecutablePage"];
let patterns = ["MemWriteOnExecutablePage", "MemOutOfBound"];
for pattern in patterns {
loop {
// Find "Pattern(digits)" and replace with just "Pattern"
// Find "Pattern(...)" and replace with just "Pattern"
let Some(start) = result.find(pattern) else { break };
let after = start + pattern.len();
let Some(rest) = result.get(after..) else { break };
if !rest.starts_with('(') { break; }
let Some(close) = rest.find(')') else { break };
// Only strip args that are alphanumeric/comma/space (e.g. "4194364, Memory" or "18")
let inside = &rest[1..close];
if !inside.chars().all(|c| c.is_ascii_digit()) { break; }
if !inside.chars().all(|c| c.is_ascii_alphanumeric() || c == ',' || c == ' ') { break; }
result = format!(
"{}{}",
&result[..after],
Expand Down
Loading