Skip to content

Commit 5050142

Browse files
authored
Merge pull request #20 from bandprotocol/refactor
Fuzz Test
2 parents 60be83f + b59abb1 commit 5050142

File tree

8 files changed

+297
-5
lines changed

8 files changed

+297
-5
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
- name: Install Rust and rust toolchain
1212
uses: actions-rs/toolchain@v1
1313
with:
14-
toolchain: nightly
14+
toolchain: stable
1515
override: true
1616

1717
- name: Install Wabt (wat2wasm)

packages/crypto/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ license = "Apache-2.0"
66
name = "owasm-crypto"
77
readme = "README.md"
88
repository = "https://github.com/bandprotocol/owasm/tree/master/packages/crypto"
9-
version = "0.2.1"
9+
version = "0.2.2"
1010

1111
[features]
1212
default = []

packages/kit/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ license = "Apache-2.0"
66
name = "owasm-kit"
77
readme = "README.md"
88
repository = "https://github.com/bandprotocol/owasm/tree/master/packages/kit"
9-
version = "0.2.1"
9+
version = "0.2.2"
1010

1111
[dependencies]
1212
num = "0.2.1"

packages/vm/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ license = "Apache-2.0"
66
name = "owasm-vm"
77
readme = "README.md"
88
repository = "https://github.com/bandprotocol/owasm/tree/master/packages/vm"
9-
version = "0.2.1"
9+
version = "0.2.2"
1010

1111
[dependencies]
1212
assert_matches = "1.3.0"
1313
clru = "0.2.0"
1414
hex = "0.4"
15-
owasm-crypto = {path = "../crypto", version = "0.2.1"}
15+
owasm-crypto = {path = "../crypto", version = "0.2.2"}
1616
sha2 = "0.9.1"
1717
tempfile = "3.1.0"
1818
wasm-instrument = "0.2.0"

packages/vm/fuzz/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
target
2+
corpus
3+
artifacts

packages/vm/fuzz/Cargo.toml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[package]
2+
name = "owasm-vm-fuzz"
3+
version = "0.2.2"
4+
authors = ["Automatically generated"]
5+
publish = false
6+
edition = "2018"
7+
8+
[package.metadata]
9+
cargo-fuzz = true
10+
11+
[dependencies]
12+
libfuzzer-sys = "0.4"
13+
tempfile = "3.1.0"
14+
15+
[dependencies.owasm-vm]
16+
path = ".."
17+
18+
# Prevent this from interfering with workspaces
19+
[workspace]
20+
members = ["."]
21+
22+
[[bin]]
23+
name = "fuzz_target_1"
24+
path = "fuzz_targets/fuzz_target_1.rs"
25+
test = false
26+
doc = false

packages/vm/fuzz/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Install cargo-fuzz
2+
3+
```sh
4+
cargo install cargo-fuzz
5+
```
6+
7+
# Run Fuzz Test
8+
9+
```sh
10+
cargo fuzz run fuzz_target_1 -- -runs=<number of run limit>
11+
```
12+
13+
** Currently, can't run on MacOS because of Sanitizer issue
14+
For details see https://github.com/google/sanitizers/issues/189
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
#![no_main]
2+
use libfuzzer_sys::fuzz_target;
3+
extern crate owasm_vm;
4+
use crate::owasm_vm::cache::*;
5+
use crate::owasm_vm::error::Error;
6+
use owasm_vm::vm::Querier;
7+
use std::io::{Read, Write};
8+
use std::process::Command;
9+
use tempfile::NamedTempFile;
10+
11+
pub struct MockQuerier {}
12+
13+
impl Querier for MockQuerier {
14+
fn get_span_size(&self) -> i64 {
15+
300
16+
}
17+
fn get_calldata(&self) -> Result<Vec<u8>, Error> {
18+
Ok(vec![1])
19+
}
20+
fn set_return_data(&self, _: &[u8]) -> Result<(), Error> {
21+
Ok(())
22+
}
23+
fn get_ask_count(&self) -> i64 {
24+
10
25+
}
26+
fn get_min_count(&self) -> i64 {
27+
8
28+
}
29+
fn get_prepare_time(&self) -> i64 {
30+
100_000
31+
}
32+
fn get_execute_time(&self) -> Result<i64, Error> {
33+
Ok(100_000)
34+
}
35+
fn get_ans_count(&self) -> Result<i64, Error> {
36+
Ok(8)
37+
}
38+
fn ask_external_data(&self, _: i64, _: i64, _: &[u8]) -> Result<(), Error> {
39+
Ok(())
40+
}
41+
fn get_external_data_status(&self, _: i64, _: i64) -> Result<i64, Error> {
42+
Ok(1)
43+
}
44+
fn get_external_data(&self, _: i64, _: i64) -> Result<Vec<u8>, Error> {
45+
Ok(vec![1])
46+
}
47+
}
48+
49+
fn wat2wasm(wat: impl AsRef<[u8]>) -> Vec<u8> {
50+
let mut input_file = NamedTempFile::new().unwrap();
51+
let mut output_file = NamedTempFile::new().unwrap();
52+
input_file.write_all(wat.as_ref()).unwrap();
53+
Command::new("wat2wasm")
54+
.args(&[
55+
input_file.path().to_str().unwrap(),
56+
"-o",
57+
output_file.path().to_str().unwrap(),
58+
"--no-check",
59+
])
60+
.output()
61+
.unwrap();
62+
let mut wasm = Vec::new();
63+
output_file.read_to_end(&mut wasm).unwrap();
64+
wasm
65+
}
66+
67+
fn generate_wat(imported_function: String) -> String {
68+
let s = format!(
69+
r#"(module
70+
{}
71+
(func (;"execute": Resolves with result "beeb";))
72+
(memory (export "memory") 512)
73+
(data (i32.const 1048576) "beeb")
74+
(export "prepare" (func 1))
75+
(export "execute" (func 2)))
76+
"#,
77+
imported_function
78+
);
79+
return s;
80+
}
81+
82+
fuzz_target!(|data: [u64; 30]| {
83+
let mut imported_wat = vec![];
84+
imported_wat.push((
85+
"get_span_size",
86+
format!(
87+
r#"(type (func (param) (result i64)))
88+
(import "env" "get_span_size" (func (type 0)))
89+
(func
90+
call 0
91+
drop
92+
)"#
93+
),
94+
));
95+
imported_wat.push((
96+
"read_calldata",
97+
format!(
98+
r#"(type (func (param i64) (result i64)))
99+
(import "env" "read_calldata" (func (type 0)))
100+
(func
101+
(i64.mul (i64.const {}) (i64.const {}))
102+
call 0
103+
drop
104+
)"#,
105+
data[28], data[29],
106+
),
107+
));
108+
imported_wat.push((
109+
"set_return_data",
110+
format!(
111+
r#"(type (func (param i64 i64) (result)))
112+
(import "env" "set_return_data" (func (type 0)))
113+
(func
114+
(i64.mul (i64.const {}) (i64.const {}))
115+
(i64.div_s (i64.const {}) (i64.const 0))
116+
call 0
117+
)"#,
118+
data[26], data[27], data[28],
119+
),
120+
));
121+
imported_wat.push((
122+
"get_ask_count",
123+
format!(
124+
r#"(type (func (param) (result i64)))
125+
(import "env" "get_ask_count" (func (type 0)))
126+
(func
127+
call 0
128+
drop
129+
)"#,
130+
),
131+
));
132+
imported_wat.push((
133+
"get_min_count",
134+
format!(
135+
r#"(type (func (param) (result i64)))
136+
(import "env" "get_min_count" (func (type 0)))
137+
(func
138+
call 0
139+
drop
140+
)"#,
141+
),
142+
));
143+
imported_wat.push((
144+
"get_prepare_time",
145+
format!(
146+
r#"(type (func (param) (result i64)))
147+
(import "env" "get_prepare_time" (func (type 0)))
148+
(func
149+
call 0
150+
drop
151+
)"#,
152+
),
153+
));
154+
imported_wat.push((
155+
"get_execute_time",
156+
format!(
157+
r#"(type (func (param) (result i64)))
158+
(import "env" "get_execute_time" (func (type 0)))
159+
(func
160+
call 0
161+
drop
162+
)"#,
163+
),
164+
));
165+
imported_wat.push((
166+
"get_ans_count",
167+
format!(
168+
r#"(type (func (param) (result i64)))
169+
(import "env" "get_ans_count" (func (type 0)))
170+
(func
171+
call 0
172+
drop
173+
)"#,
174+
),
175+
));
176+
imported_wat.push((
177+
"get_external_data_status",
178+
format!(
179+
r#"(type (func (param i64 i64) (result i64)))
180+
(import "env" "get_external_data_status" (func (type 0)))
181+
(func
182+
(i64.div_s (i64.const {}) (i64.const {}))
183+
(i64.mul (i64.const {}) (i64.const {}))
184+
call 0
185+
drop
186+
)"#,
187+
data[26], data[27], data[28], data[29]
188+
),
189+
));
190+
imported_wat.push((
191+
"ask_external_data",
192+
format!(
193+
r#"(type (func (param i64 i64 i64 i64) (result)))
194+
(import "env" "ask_external_data" (func (type 0)))
195+
(func
196+
(i64.mul (i64.const {}) (i64.const {}))
197+
(i64.div_s (i64.const 0) (i64.const {}))
198+
(i64.div_s (i64.const {}) (i64.const 0))
199+
(i64.div_s (i64.const 0) (i64.const 0))
200+
call 0
201+
)"#,
202+
data[26], data[27], data[28], data[29]
203+
),
204+
));
205+
imported_wat.push((
206+
"read_external_data",
207+
format!(
208+
r#"(type (func (param i64 i64 i64) (result i64)))
209+
(import "env" "read_external_data" (func (type 0)))
210+
(func
211+
(i64.div_s (i64.const {}) (i64.const {}))
212+
(i64.mul (i64.const {}) (i64.const {}))
213+
(i64.sub (i64.const {}) (i64.const {}))
214+
call 0
215+
drop
216+
)"#,
217+
data[24], data[25], data[26], data[27], data[28], data[29]
218+
),
219+
));
220+
imported_wat.push((
221+
"ecvrf_verify",
222+
format!(
223+
r#"(type (func (param i64 i64 i64 i64 i64 i64) (result i32)))
224+
(import "env" "ecvrf_verify" (func (type 0)))
225+
(func
226+
(i64.mul (i64.const {}) (i64.const {}))
227+
(i64.add (i64.const {}) (i64.const {}))
228+
(i64.add (i64.const {}) (i64.const 0))
229+
(i64.sub (i64.const {}) (i64.const {}))
230+
(i64.sub (i64.const {}) (i64.const 0))
231+
(i64.sub (i64.const 0) (i64.const 0))
232+
call 0
233+
drop
234+
)"#,
235+
data[22], data[23], data[24], data[25], data[26], data[27], data[28], data[29]
236+
),
237+
));
238+
for (_func, wat) in &imported_wat {
239+
// println!("======================");
240+
// println!("{:?}", func);
241+
let s = generate_wat(wat.clone());
242+
// println!("{}", s);
243+
let wasm = wat2wasm(s);
244+
let code = owasm_vm::compile(&wasm).unwrap();
245+
let mut cache = Cache::new(CacheOptions { cache_size: 10000 });
246+
let _gas = owasm_vm::run(&mut cache, &code, u64::MAX, true, MockQuerier {});
247+
// println!("{:?}", gas);
248+
}
249+
});

0 commit comments

Comments
 (0)