Skip to content

Commit 278fe1c

Browse files
committed
Fix linkage issue
1 parent f412a78 commit 278fe1c

File tree

5 files changed

+52
-57
lines changed

5 files changed

+52
-57
lines changed

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ pyo3-log = { version = "0.12.2", optional = true }
3737

3838
[features]
3939
default = []
40-
bindings = ["pyo3", "pyo3-log", "env_logger"]
40+
bindings = [
41+
"unicorn-engine/dynamic_linkage"
42+
]
43+
python = [
44+
"pyo3", "pyo3-log", "env_logger", "bindings"
45+
]
4146

4247
[lib]
4348
name = "unicornafl"

Readme.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ For python bindings, we have:
4646
maturin build --release
4747
```
4848

49+
## Unicorn Linkage
50+
51+
Please note that, unicorn is already bundled with unicornafl by default and you **shall not** pass unicorn engine pointer created by another unicorn dynamic library.
52+
53+
For Rust, stick to `unicornafl::unicorn_engine::*` to avoid incorrect structs and pointers. Refer to [Rust usage](./docs/rust-usage.md) for more details on override dependencies.
54+
55+
For Python, you are free to use `from unicorn import Uc` because Python only allows dynamic linkage and we will always use the copy from the Unicorn python bindings.
56+
57+
For C/C++, similar to Python, you should provide a dynamic unicorn library which our unicornafl will pick.
58+
4959
## Example && Minimal Tutorial
5060

5161
We provide a sample harness at [the examples](https://github.com/AFLplusplus/AFLplusplus/tree/stable/unicorn_mode/samples).

docs/c-usage.md

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ To use UnicornAFL with C/C++, you should clone this repository and build it your
44

55
```shell
66
git clone --depth 1 https://github.com/AFLplusplus/unicornafl && cd unicornafl
7-
cargo build --release
7+
cargo build --release --features bindings
88
```
99

1010
Before building this repo, make sure that you have installed dependencies to build [Unicorn](https://github.com/unicorn-engine/unicorn), and installed stable Rust compiler with at least 1.87.0.
@@ -67,34 +67,6 @@ Before using fuzzing APIs, you should create unicorn instance on your own. It sh
6767

6868
## Tips
6969

70-
### Linking
71-
72-
Note that `libunicornafl.a` or `libunicornafl.so` already bundles a Unicorn. As a result, you don't need to manually link Unicorn any more.
73-
74-
### Use a different version of Unicorn
75-
76-
It should be noted that the internal of UnicornAFL depends heavily on some newest Unicorn APIs. As a result, older version of Unicorn may not work. However, if you want to use your own version of Unicorn, you should modify the `Cargo.toml` in this repo.
77-
78-
First, find the following line:
79-
80-
```toml
81-
unicorn-engine = { git = "https://github.com/unicorn-engine/unicorn", branch = "dev" }
82-
```
83-
84-
If you want to use a Unicorn in local filesystem, you should change this line to
85-
86-
```toml
87-
unicorn-engine = { path = "/path/to/unicorn/bindings/rust" }
88-
```
89-
90-
Note that the `bindings/rust` suffix is necessary.
91-
92-
If you want to use a forked Unicorn or Unicorn in remote Git server, you should change this line to
93-
94-
```toml
95-
unicorn-engine = { git = "http://my/own/unicorn/fork" }
96-
```
97-
9870
### Debugging
9971

10072
Inside UnicornAFL, there are many logs could be used for debugging. To enable logging, you should compile this repo using

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ dependencies = ["unicorn>=2.1.3"]
1616
[tool.maturin]
1717
bindings = "pyo3"
1818
manifest-path = "Cargo.toml"
19-
features = ["bindings"]
19+
features = ["python"]
2020
python-source = "python"
2121
compatibility = "manylinux_2_28"

src/lib.rs

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ use std::{
66
};
77

88
use executor::{UnicornAflExecutorCustomHook, UnicornAflExecutorHook, UnicornFuzzData};
9-
use unicorn_engine::{Unicorn, uc_error, unicorn_const::uc_engine};
9+
10+
pub mod unicorn_engine {
11+
pub use unicorn_engine::*;
12+
}
1013

1114
pub mod executor;
1215
mod forkserver;
@@ -36,15 +39,15 @@ impl From<libafl::Error> for uc_afl_ret {
3639
}
3740
}
3841

39-
impl From<uc_error> for uc_afl_ret {
40-
fn from(_: uc_error) -> Self {
42+
impl From<unicorn_engine::uc_error> for uc_afl_ret {
43+
fn from(_: unicorn_engine::uc_error) -> Self {
4144
Self::UC_AFL_RET_UC_ERR
4245
}
4346
}
4447

4548
#[allow(non_camel_case_types)]
4649
pub type uc_afl_cb_place_input_t = extern "C" fn(
47-
uc: *mut uc_engine,
50+
uc: *mut unicorn_engine::uc_engine,
4851
input: *const c_uchar,
4952
input_len: usize,
5053
persistent_round: u64,
@@ -53,16 +56,19 @@ pub type uc_afl_cb_place_input_t = extern "C" fn(
5356

5457
#[allow(non_camel_case_types)]
5558
pub type uc_afl_cb_validate_crash_t = extern "C" fn(
56-
uc: *mut uc_engine,
57-
unicorn_result: uc_error,
59+
uc: *mut unicorn_engine::uc_engine,
60+
unicorn_result: unicorn_engine::uc_error,
5861
input: *const c_uchar,
5962
input_len: usize,
6063
persistent_round: u64,
6164
data: *mut c_void,
6265
) -> bool;
6366

6467
#[allow(non_camel_case_types)]
65-
pub type uc_afl_fuzz_cb_t = extern "C" fn(uc: *mut uc_engine, data: *mut c_void) -> uc_error;
68+
pub type uc_afl_fuzz_cb_t = extern "C" fn(
69+
uc: *mut unicorn_engine::uc_engine,
70+
data: *mut c_void,
71+
) -> unicorn_engine::uc_error;
6672

6773
/// Customized afl fuzz routine entrypoint for Rust user.
6874
///
@@ -76,7 +82,7 @@ pub type uc_afl_fuzz_cb_t = extern "C" fn(uc: *mut uc_engine, data: *mut c_void)
7682
/// `persistent_iters` is the number of persistent execution rounds. If it is `None`,
7783
/// then the loop will be infinite
7884
pub fn afl_fuzz_custom<'a, D: 'a>(
79-
uc: Unicorn<'a, UnicornFuzzData<D>>,
85+
uc: unicorn_engine::Unicorn<'a, UnicornFuzzData<D>>,
8086
input_file: Option<PathBuf>,
8187
callbacks: impl UnicornAflExecutorHook<'a, D>,
8288
exits: Vec<u64>,
@@ -98,9 +104,10 @@ pub fn afl_fuzz_custom<'a, D: 'a>(
98104
///
99105
/// If you want to manually validate crash or kick fuzzing, call [`afl_fuzz_custom`].
100106
pub fn afl_fuzz<'a, D: 'a>(
101-
uc: Unicorn<'a, UnicornFuzzData<D>>,
107+
uc: unicorn_engine::Unicorn<'a, UnicornFuzzData<D>>,
102108
input_file: Option<PathBuf>,
103-
place_input_cb: impl FnMut(&mut Unicorn<'a, UnicornFuzzData<D>>, &[u8], u64) -> bool + 'a,
109+
place_input_cb: impl FnMut(&mut unicorn_engine::Unicorn<'a, UnicornFuzzData<D>>, &[u8], u64) -> bool
110+
+ 'a,
104111
exits: Vec<u64>,
105112
persistent_iters: Option<u64>,
106113
) -> Result<(), uc_afl_ret> {
@@ -122,7 +129,7 @@ pub fn afl_fuzz<'a, D: 'a>(
122129
#[unsafe(no_mangle)]
123130
#[allow(non_camel_case_types)]
124131
pub extern "C" fn uc_afl_fuzz(
125-
uc_handle: *mut uc_engine,
132+
uc_handle: *mut unicorn_engine::uc_engine,
126133
input_file: *const c_char,
127134
place_input_callback: uc_afl_cb_place_input_t,
128135
exits: *const u64,
@@ -150,7 +157,7 @@ pub extern "C" fn uc_afl_fuzz(
150157
#[unsafe(no_mangle)]
151158
#[allow(non_camel_case_types)]
152159
pub extern "C" fn uc_afl_fuzz_custom(
153-
uc_handle: *mut uc_engine,
160+
uc_handle: *mut unicorn_engine::uc_engine,
154161
input_file: *const c_char,
155162
place_input_callback: uc_afl_cb_place_input_t,
156163
fuzz_callback: uc_afl_fuzz_cb_t,
@@ -179,7 +186,7 @@ pub extern "C" fn uc_afl_fuzz_custom(
179186
// to avoid checking the emptyness inside every round.
180187
#[expect(clippy::too_many_arguments)]
181188
fn uc_afl_fuzz_internal(
182-
uc_handle: *mut uc_engine,
189+
uc_handle: *mut unicorn_engine::uc_engine,
183190
input_file: *const c_char,
184191
place_input_callback: uc_afl_cb_place_input_t,
185192
exits: *const u64,
@@ -191,31 +198,32 @@ fn uc_afl_fuzz_internal(
191198
data: *mut c_void,
192199
) -> uc_afl_ret {
193200
let fuzz_data = UnicornFuzzData::new(data);
194-
let uc = match unsafe { Unicorn::from_handle_with_data(uc_handle, fuzz_data) } {
201+
let uc = match unsafe { unicorn_engine::Unicorn::from_handle_with_data(uc_handle, fuzz_data) } {
195202
Ok(uc) => uc,
196203
Err(err) => {
197204
return err.into();
198205
}
199206
};
200207

201-
let place_input_cb = move |uc: &mut Unicorn<'_, UnicornFuzzData<*mut c_void>>,
202-
input: &[u8],
203-
persistent_round: u64| {
204-
let handle = uc.get_handle();
205-
let data = uc.get_data_mut().user_data;
206-
(place_input_callback)(handle, input.as_ptr(), input.len(), persistent_round, data)
207-
};
208+
let place_input_cb =
209+
move |uc: &mut unicorn_engine::Unicorn<'_, UnicornFuzzData<*mut c_void>>,
210+
input: &[u8],
211+
persistent_round: u64| {
212+
let handle = uc.get_handle();
213+
let data = uc.get_data_mut().user_data;
214+
(place_input_callback)(handle, input.as_ptr(), input.len(), persistent_round, data)
215+
};
208216
let validate_crash_cb = validate_crash_callback.map(|validate_crash_callback| {
209-
move |uc: &mut Unicorn<'_, UnicornFuzzData<*mut c_void>>,
210-
unicorn_result: Result<(), uc_error>,
217+
move |uc: &mut unicorn_engine::Unicorn<'_, UnicornFuzzData<*mut c_void>>,
218+
unicorn_result: Result<(), unicorn_engine::uc_error>,
211219
input: &[u8],
212220
persistent_round: u64| {
213221
let handle = uc.get_handle();
214222
let data = uc.get_data_mut().user_data;
215223
let unicorn_result = if let Err(err) = unicorn_result {
216224
err
217225
} else {
218-
uc_error::OK
226+
unicorn_engine::uc_error::OK
219227
};
220228
(validate_crash_callback)(
221229
handle,
@@ -228,11 +236,11 @@ fn uc_afl_fuzz_internal(
228236
}
229237
});
230238
let fuzz_cb = fuzz_callback.map(|fuzz_callback| {
231-
move |uc: &mut Unicorn<'_, UnicornFuzzData<*mut c_void>>| {
239+
move |uc: &mut unicorn_engine::Unicorn<'_, UnicornFuzzData<*mut c_void>>| {
232240
let handle = uc.get_handle();
233241
let data = uc.get_data_mut().user_data;
234242
let unicorn_result = fuzz_callback(handle, data);
235-
if unicorn_result == uc_error::OK {
243+
if unicorn_result == unicorn_engine::uc_error::OK {
236244
Ok(())
237245
} else {
238246
Err(unicorn_result)

0 commit comments

Comments
 (0)