Update dependencies, removed unused deps, CI fixes (#839)
* update clap, remove unused deps * update grammartek * update pyo3 * update pyo3 * undid clap update * not changing nyx * updated deps * Update more deps, fixes * not needed clippy * fix windows * try to enable deprecated pyproto for pyo3 * unused * moving some things to clap4 after all * initial move to clap 4 * fix clap * more clap4, removed accidental file * fixes, fmt * fix * all fix no play * fix
This commit is contained in:
parent
d6d4fa506b
commit
e8b3d33bf4
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
target
|
target
|
||||||
|
target-bin
|
||||||
out
|
out
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
vendor
|
vendor
|
||||||
@ -48,4 +49,4 @@ __pycache__
|
|||||||
*atomic_file_testfile*
|
*atomic_file_testfile*
|
||||||
**/libxml2
|
**/libxml2
|
||||||
**/corpus_discovered
|
**/corpus_discovered
|
||||||
**/libxml2-*.tar.gz
|
**/libxml2-*.tar.gz
|
||||||
|
@ -4,13 +4,13 @@ version = "0.8.2"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pyo3 = { version = "0.15", features = ["extension-module"] }
|
pyo3 = { version = "0.17", features = ["extension-module"] }
|
||||||
libafl_qemu = { path = "../../libafl_qemu", version = "0.8.2", features = ["python"] }
|
libafl_qemu = { path = "../../libafl_qemu", version = "0.8.2", features = ["python"] }
|
||||||
libafl_sugar = { path = "../../libafl_sugar", version = "0.8.2", features = ["python"] }
|
libafl_sugar = { path = "../../libafl_sugar", version = "0.8.2", features = ["python"] }
|
||||||
libafl = { path = "../../libafl", version = "0.8.2", features = ["python"] }
|
libafl = { path = "../../libafl", version = "0.8.2", features = ["python"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
pyo3-build-config = { version = "0.15" }
|
pyo3-build-config = { version = "0.17" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "pylibafl"
|
name = "pylibafl"
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# How to use python bindings
|
# How to use python bindings
|
||||||
## First time setup
|
## First time setup
|
||||||
```
|
```bash
|
||||||
# Create environment variable
|
|
||||||
python -m venv .env
|
|
||||||
# Install maturin
|
# Install maturin
|
||||||
pip install maturin
|
pip install maturin
|
||||||
|
# Create virtual environment
|
||||||
|
python3 -m venv .env
|
||||||
```
|
```
|
||||||
## Build bindings
|
## Build bindings
|
||||||
```
|
```
|
||||||
@ -13,7 +13,7 @@ source .env/bin/activate
|
|||||||
# Build python module
|
# Build python module
|
||||||
maturin develop
|
maturin develop
|
||||||
```
|
```
|
||||||
This is going to install `pylibafl` python module.
|
This is going to install `pylibafl` python module into this venv.
|
||||||
|
|
||||||
## Use bindings
|
## Use bindings
|
||||||
### Example: Running baby_fuzzer in fuzzers/baby_fuzzer/baby_fuzzer.py
|
### Example: Running baby_fuzzer in fuzzers/baby_fuzzer/baby_fuzzer.py
|
||||||
@ -28,4 +28,4 @@ Then simply run
|
|||||||
```
|
```
|
||||||
python PATH_TO_BABY_FUZZER/baby_fuzzer.py
|
python PATH_TO_BABY_FUZZER/baby_fuzzer.py
|
||||||
```
|
```
|
||||||
The crashes' directory will be created in the directory from which you ran the command.
|
The crashes directory will be created in the directory from which you ran the command.
|
||||||
|
@ -18,4 +18,4 @@ opt-level = 3
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = { path = "../../libafl/" }
|
libafl = { path = "../../libafl/" }
|
||||||
clap = { version = "3.2", features = ["default"] }
|
clap = { version = "3.2", features = ["default"] }
|
||||||
nix = "0.24"
|
nix = "0.25"
|
||||||
|
@ -74,7 +74,9 @@ pub fn main() {
|
|||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let corpus_dirs = vec![PathBuf::from(res.value_of("in").unwrap().to_string())];
|
let corpus_dirs = vec![PathBuf::from(
|
||||||
|
res.get_one::<String>("in").unwrap().to_string(),
|
||||||
|
)];
|
||||||
|
|
||||||
const MAP_SIZE: usize = 65536;
|
const MAP_SIZE: usize = 65536;
|
||||||
|
|
||||||
@ -159,7 +161,7 @@ pub fn main() {
|
|||||||
|
|
||||||
let mut tokens = Tokens::new();
|
let mut tokens = Tokens::new();
|
||||||
let forkserver = ForkserverExecutor::builder()
|
let forkserver = ForkserverExecutor::builder()
|
||||||
.program(res.value_of("executable").unwrap())
|
.program(res.get_one::<String>("executable").unwrap())
|
||||||
.debug_child(debug_child)
|
.debug_child(debug_child)
|
||||||
.shmem_provider(&mut shmem_provider)
|
.shmem_provider(&mut shmem_provider)
|
||||||
.autotokens(&mut tokens)
|
.autotokens(&mut tokens)
|
||||||
@ -170,13 +172,16 @@ pub fn main() {
|
|||||||
let mut executor = TimeoutForkserverExecutor::with_signal(
|
let mut executor = TimeoutForkserverExecutor::with_signal(
|
||||||
forkserver,
|
forkserver,
|
||||||
Duration::from_millis(
|
Duration::from_millis(
|
||||||
res.value_of("timeout")
|
res.get_one::<String>("timeout")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string()
|
.to_string()
|
||||||
.parse()
|
.parse()
|
||||||
.expect("Could not parse timeout in milliseconds"),
|
.expect("Could not parse timeout in milliseconds"),
|
||||||
),
|
),
|
||||||
res.value_of("signal").unwrap().parse::<Signal>().unwrap(),
|
res.get_one::<String>("signal")
|
||||||
|
.unwrap()
|
||||||
|
.parse::<Signal>()
|
||||||
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.expect("Failed to create the executor.");
|
.expect("Failed to create the executor.");
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ libc = "0.2"
|
|||||||
libloading = "0.7"
|
libloading = "0.7"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
rangemap = "0.1"
|
rangemap = "0.1"
|
||||||
clap = { version = "3.2", features = ["derive"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
mimalloc = { version = "*", default-features = false }
|
mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ libc = "0.2"
|
|||||||
libloading = "0.7"
|
libloading = "0.7"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
rangemap = "0.1"
|
rangemap = "0.1"
|
||||||
clap = { version = "3.2", features = ["derive"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
mimalloc = { version = "*", default-features = false }
|
mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ libafl = { path = "../../libafl/" }
|
|||||||
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "sancov_cmplog", "libfuzzer"] }
|
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "sancov_cmplog", "libfuzzer"] }
|
||||||
# TODO Include it only when building cc
|
# TODO Include it only when building cc
|
||||||
libafl_cc = { path = "../../libafl_cc/" }
|
libafl_cc = { path = "../../libafl_cc/" }
|
||||||
clap = { version = "3.2", features = ["default"] }
|
clap = { version = "4.0", features = ["default"] }
|
||||||
nix = "0.24"
|
nix = "0.25"
|
||||||
mimalloc = { version = "*", default-features = false }
|
mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
BIN
fuzzers/fuzzbench/server
Executable file
BIN
fuzzers/fuzzbench/server
Executable file
Binary file not shown.
@ -71,22 +71,19 @@ pub fn libafl_main() {
|
|||||||
Arg::new("out")
|
Arg::new("out")
|
||||||
.short('o')
|
.short('o')
|
||||||
.long("output")
|
.long("output")
|
||||||
.help("The directory to place finds in ('corpus')")
|
.help("The directory to place finds in ('corpus')"),
|
||||||
.takes_value(true),
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("in")
|
Arg::new("in")
|
||||||
.short('i')
|
.short('i')
|
||||||
.long("input")
|
.long("input")
|
||||||
.help("The directory to read initial inputs from ('seeds')")
|
.help("The directory to read initial inputs from ('seeds')"),
|
||||||
.takes_value(true),
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("tokens")
|
Arg::new("tokens")
|
||||||
.short('x')
|
.short('x')
|
||||||
.long("tokens")
|
.long("tokens")
|
||||||
.help("A file to read tokens from, to be used during fuzzing")
|
.help("A file to read tokens from, to be used during fuzzing"),
|
||||||
.takes_value(true),
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("logfile")
|
Arg::new("logfile")
|
||||||
@ -102,7 +99,7 @@ pub fn libafl_main() {
|
|||||||
.help("Timeout for each individual execution, in milliseconds")
|
.help("Timeout for each individual execution, in milliseconds")
|
||||||
.default_value("1200"),
|
.default_value("1200"),
|
||||||
)
|
)
|
||||||
.arg(Arg::new("remaining").multiple_values(true))
|
.arg(Arg::new("remaining"))
|
||||||
.try_get_matches()
|
.try_get_matches()
|
||||||
{
|
{
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
@ -123,8 +120,8 @@ pub fn libafl_main() {
|
|||||||
env::current_dir().unwrap().to_string_lossy().to_string()
|
env::current_dir().unwrap().to_string_lossy().to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(filenames) = res.values_of("remaining") {
|
if let Some(filenames) = res.get_many::<String>("remaining") {
|
||||||
let filenames: Vec<&str> = filenames.collect();
|
let filenames: Vec<&str> = filenames.map(|v| v.as_str()).collect();
|
||||||
if !filenames.is_empty() {
|
if !filenames.is_empty() {
|
||||||
run_testcases(&filenames);
|
run_testcases(&filenames);
|
||||||
return;
|
return;
|
||||||
@ -133,7 +130,7 @@ pub fn libafl_main() {
|
|||||||
|
|
||||||
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
|
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
|
||||||
let mut out_dir = PathBuf::from(
|
let mut out_dir = PathBuf::from(
|
||||||
res.value_of("out")
|
res.get_one::<String>("out")
|
||||||
.expect("The --output parameter is missing")
|
.expect("The --output parameter is missing")
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
@ -149,7 +146,7 @@ pub fn libafl_main() {
|
|||||||
out_dir.push("queue");
|
out_dir.push("queue");
|
||||||
|
|
||||||
let in_dir = PathBuf::from(
|
let in_dir = PathBuf::from(
|
||||||
res.value_of("in")
|
res.get_one::<String>("in")
|
||||||
.expect("The --input parameter is missing")
|
.expect("The --input parameter is missing")
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
@ -158,14 +155,13 @@ pub fn libafl_main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokens = res.value_of("tokens").map(PathBuf::from);
|
let tokens = res.get_one::<String>("tokens").map(PathBuf::from);
|
||||||
|
|
||||||
let logfile = PathBuf::from(res.value_of("logfile").unwrap().to_string());
|
let logfile = PathBuf::from(res.get_one::<String>("logfile").unwrap());
|
||||||
|
|
||||||
let timeout = Duration::from_millis(
|
let timeout = Duration::from_millis(
|
||||||
res.value_of("timeout")
|
res.get_one::<String>("timeout")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string()
|
|
||||||
.parse()
|
.parse()
|
||||||
.expect("Could not parse timeout in milliseconds"),
|
.expect("Could not parse timeout in milliseconds"),
|
||||||
);
|
);
|
||||||
|
@ -15,4 +15,4 @@ debug = true
|
|||||||
libafl = { path = "../../libafl/" }
|
libafl = { path = "../../libafl/" }
|
||||||
libafl_qemu = { path = "../../libafl_qemu/", features = ["x86_64"] }
|
libafl_qemu = { path = "../../libafl_qemu/", features = ["x86_64"] }
|
||||||
clap = { version = "3.2", features = ["default"] }
|
clap = { version = "3.2", features = ["default"] }
|
||||||
nix = "0.24"
|
nix = "0.25"
|
||||||
|
@ -113,7 +113,7 @@ pub fn main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
|
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
|
||||||
let mut out_dir = PathBuf::from(res.value_of("out").unwrap().to_string());
|
let mut out_dir = PathBuf::from(res.get_one::<String>("out").unwrap().to_string());
|
||||||
if fs::create_dir(&out_dir).is_err() {
|
if fs::create_dir(&out_dir).is_err() {
|
||||||
println!("Out dir at {:?} already exists.", &out_dir);
|
println!("Out dir at {:?} already exists.", &out_dir);
|
||||||
if !out_dir.is_dir() {
|
if !out_dir.is_dir() {
|
||||||
@ -125,15 +125,15 @@ pub fn main() {
|
|||||||
crashes.push("crashes");
|
crashes.push("crashes");
|
||||||
out_dir.push("queue");
|
out_dir.push("queue");
|
||||||
|
|
||||||
let in_dir = PathBuf::from(res.value_of("in").unwrap().to_string());
|
let in_dir = PathBuf::from(res.get_one::<String>("in").unwrap().to_string());
|
||||||
if !in_dir.is_dir() {
|
if !in_dir.is_dir() {
|
||||||
println!("In dir at {:?} is not a valid directory!", &in_dir);
|
println!("In dir at {:?} is not a valid directory!", &in_dir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokens = res.value_of("tokens").map(PathBuf::from);
|
let tokens = res.get_one::<String>("tokens").map(PathBuf::from);
|
||||||
|
|
||||||
let logfile = PathBuf::from(res.value_of("logfile").unwrap().to_string());
|
let logfile = PathBuf::from(res.get_one::<String>("logfile").unwrap().to_string());
|
||||||
|
|
||||||
fuzz(out_dir, crashes, in_dir, tokens, logfile).expect("An error occurred while fuzzing");
|
fuzz(out_dir, crashes, in_dir, tokens, logfile).expect("An error occurred while fuzzing");
|
||||||
}
|
}
|
||||||
|
@ -15,4 +15,4 @@ debug = true
|
|||||||
libafl = { path = "../../libafl/" }
|
libafl = { path = "../../libafl/" }
|
||||||
libafl_qemu = { path = "../../libafl_qemu/", features = ["x86_64"] }
|
libafl_qemu = { path = "../../libafl_qemu/", features = ["x86_64"] }
|
||||||
clap = { version = "3.2", features = ["default"] }
|
clap = { version = "3.2", features = ["default"] }
|
||||||
nix = "0.24"
|
nix = "0.25"
|
||||||
|
@ -125,7 +125,7 @@ pub fn main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
|
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
|
||||||
let mut out_dir = PathBuf::from(res.value_of("out").unwrap().to_string());
|
let mut out_dir = PathBuf::from(res.get_one::<String>("out").unwrap().to_string());
|
||||||
if fs::create_dir(&out_dir).is_err() {
|
if fs::create_dir(&out_dir).is_err() {
|
||||||
println!("Out dir at {:?} already exists.", &out_dir);
|
println!("Out dir at {:?} already exists.", &out_dir);
|
||||||
if !out_dir.is_dir() {
|
if !out_dir.is_dir() {
|
||||||
@ -137,18 +137,18 @@ pub fn main() {
|
|||||||
crashes.push("crashes");
|
crashes.push("crashes");
|
||||||
out_dir.push("queue");
|
out_dir.push("queue");
|
||||||
|
|
||||||
let in_dir = PathBuf::from(res.value_of("in").unwrap().to_string());
|
let in_dir = PathBuf::from(res.get_one::<String>("in").unwrap().to_string());
|
||||||
if !in_dir.is_dir() {
|
if !in_dir.is_dir() {
|
||||||
println!("In dir at {:?} is not a valid directory!", &in_dir);
|
println!("In dir at {:?} is not a valid directory!", &in_dir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokens = res.value_of("tokens").map(PathBuf::from);
|
let tokens = res.get_one::<String>("tokens").map(PathBuf::from);
|
||||||
|
|
||||||
let logfile = PathBuf::from(res.value_of("logfile").unwrap().to_string());
|
let logfile = PathBuf::from(res.get_one::<String>("logfile").unwrap().to_string());
|
||||||
|
|
||||||
let timeout = Duration::from_millis(
|
let timeout = Duration::from_millis(
|
||||||
res.value_of("timeout")
|
res.get_one::<String>("timeout")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string()
|
.to_string()
|
||||||
.parse()
|
.parse()
|
||||||
|
@ -24,7 +24,7 @@ libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_h
|
|||||||
# TODO Include it only when building cc
|
# TODO Include it only when building cc
|
||||||
libafl_cc = { path = "../../libafl_cc/" }
|
libafl_cc = { path = "../../libafl_cc/" }
|
||||||
clap = { version = "3.2", features = ["default"] }
|
clap = { version = "3.2", features = ["default"] }
|
||||||
nix = "0.24"
|
nix = "0.25"
|
||||||
mimalloc = { version = "*", default-features = false }
|
mimalloc = { version = "*", default-features = false }
|
||||||
content_inspector = "0.2.4"
|
content_inspector = "0.2.4"
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ pub fn libafl_main() {
|
|||||||
|
|
||||||
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
|
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
|
||||||
let mut out_dir = PathBuf::from(
|
let mut out_dir = PathBuf::from(
|
||||||
res.value_of("out")
|
res.get_one::<String>("out")
|
||||||
.expect("The --output parameter is missing")
|
.expect("The --output parameter is missing")
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
@ -155,7 +155,7 @@ pub fn libafl_main() {
|
|||||||
out_dir.push("queue");
|
out_dir.push("queue");
|
||||||
|
|
||||||
let in_dir = PathBuf::from(
|
let in_dir = PathBuf::from(
|
||||||
res.value_of("in")
|
res.get_one::<String>("in")
|
||||||
.expect("The --input parameter is missing")
|
.expect("The --input parameter is missing")
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
@ -164,12 +164,12 @@ pub fn libafl_main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokens = res.value_of("tokens").map(PathBuf::from);
|
let tokens = res.get_one::<String>("tokens").map(PathBuf::from);
|
||||||
|
|
||||||
let logfile = PathBuf::from(res.value_of("logfile").unwrap().to_string());
|
let logfile = PathBuf::from(res.get_one::<String>("logfile").unwrap().to_string());
|
||||||
|
|
||||||
let timeout = Duration::from_millis(
|
let timeout = Duration::from_millis(
|
||||||
res.value_of("timeout")
|
res.get_one::<String>("timeout")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string()
|
.to_string()
|
||||||
.parse()
|
.parse()
|
||||||
|
@ -24,7 +24,7 @@ libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_h
|
|||||||
# TODO Include it only when building cc
|
# TODO Include it only when building cc
|
||||||
libafl_cc = { path = "../../libafl_cc/" }
|
libafl_cc = { path = "../../libafl_cc/" }
|
||||||
clap = { version = "3.2", features = ["default"] }
|
clap = { version = "3.2", features = ["default"] }
|
||||||
nix = "0.24"
|
nix = "0.25"
|
||||||
mimalloc = { version = "*", default-features = false }
|
mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
@ -133,7 +133,7 @@ pub fn libafl_main() {
|
|||||||
|
|
||||||
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
|
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
|
||||||
let mut out_dir = PathBuf::from(
|
let mut out_dir = PathBuf::from(
|
||||||
res.value_of("out")
|
res.get_one::<String>("out")
|
||||||
.expect("The --output parameter is missing")
|
.expect("The --output parameter is missing")
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
@ -149,7 +149,7 @@ pub fn libafl_main() {
|
|||||||
out_dir.push("queue");
|
out_dir.push("queue");
|
||||||
|
|
||||||
let in_dir = PathBuf::from(
|
let in_dir = PathBuf::from(
|
||||||
res.value_of("in")
|
res.get_one::<String>("in")
|
||||||
.expect("The --input parameter is missing")
|
.expect("The --input parameter is missing")
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
@ -158,12 +158,12 @@ pub fn libafl_main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokens = res.value_of("tokens").map(PathBuf::from);
|
let tokens = res.get_one::<String>("tokens").map(PathBuf::from);
|
||||||
|
|
||||||
let logfile = PathBuf::from(res.value_of("logfile").unwrap().to_string());
|
let logfile = PathBuf::from(res.get_one::<String>("logfile").unwrap().to_string());
|
||||||
|
|
||||||
let timeout = Duration::from_millis(
|
let timeout = Duration::from_millis(
|
||||||
res.value_of("timeout")
|
res.get_one::<String>("timeout")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string()
|
.to_string()
|
||||||
.parse()
|
.parse()
|
||||||
|
@ -180,21 +180,21 @@ pub fn LLVMFuzzerRunDriver(
|
|||||||
env::current_dir().unwrap().to_string_lossy().to_string()
|
env::current_dir().unwrap().to_string_lossy().to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
let cores = Cores::from_cmdline(matches.value_of("cores").unwrap())
|
let cores = Cores::from_cmdline(matches.get_one::<String>("cores").unwrap())
|
||||||
.expect("No valid core count given!");
|
.expect("No valid core count given!");
|
||||||
let broker_port = matches
|
let broker_port = matches
|
||||||
.value_of("broker_port")
|
.get_one::<String>("broker_port")
|
||||||
.map(|s| s.parse().expect("Invalid broker port"))
|
.map(|s| s.parse().expect("Invalid broker port"))
|
||||||
.unwrap_or(1337);
|
.unwrap_or(1337);
|
||||||
let remote_broker_addr = matches
|
let remote_broker_addr = matches
|
||||||
.value_of("remote_broker_addr")
|
.get_one::<String>("remote_broker_addr")
|
||||||
.map(|s| s.parse().expect("Invalid broker address"));
|
.map(|s| s.parse().expect("Invalid broker address"));
|
||||||
let input_dirs: Vec<PathBuf> = matches
|
let input_dirs: Vec<PathBuf> = matches
|
||||||
.values_of("input")
|
.values_of("input")
|
||||||
.map(|v| v.map(PathBuf::from).collect())
|
.map(|v| v.map(PathBuf::from).collect())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let output_dir = matches
|
let output_dir = matches
|
||||||
.value_of("output")
|
.get_one::<String>("output")
|
||||||
.map(PathBuf::from)
|
.map(PathBuf::from)
|
||||||
.unwrap_or_else(|| workdir.clone());
|
.unwrap_or_else(|| workdir.clone());
|
||||||
let token_files: Vec<&str> = matches
|
let token_files: Vec<&str> = matches
|
||||||
@ -202,7 +202,7 @@ pub fn LLVMFuzzerRunDriver(
|
|||||||
.map(|v| v.collect())
|
.map(|v| v.collect())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let timeout_ms = matches
|
let timeout_ms = matches
|
||||||
.value_of("timeout")
|
.get_one::<String>("timeout")
|
||||||
.map(|s| s.parse().expect("Invalid timeout"))
|
.map(|s| s.parse().expect("Invalid timeout"))
|
||||||
.unwrap_or(10000);
|
.unwrap_or(10000);
|
||||||
// let cmplog_enabled = matches.is_present("cmplog");
|
// let cmplog_enabled = matches.is_present("cmplog");
|
||||||
|
@ -23,7 +23,7 @@ libafl = { path = "../../libafl/", features = ["std", "derive", "llmp_compressio
|
|||||||
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer"] }
|
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer"] }
|
||||||
# TODO Include it only when building cc
|
# TODO Include it only when building cc
|
||||||
libafl_cc = { path = "../../libafl_cc/" }
|
libafl_cc = { path = "../../libafl_cc/" }
|
||||||
clap = { version = "3.2", features = ["derive"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
mimalloc = { version = "*", default-features = false }
|
mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
@ -9,7 +9,7 @@ static GLOBAL: MiMalloc = MiMalloc;
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use std::{env, net::SocketAddr, path::PathBuf};
|
use std::{env, net::SocketAddr, path::PathBuf};
|
||||||
|
|
||||||
use clap::{self, StructOpt};
|
use clap::Parser;
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{
|
bolts::{
|
||||||
core_affinity::Cores,
|
core_affinity::Cores,
|
||||||
@ -48,23 +48,23 @@ fn timeout_from_millis_str(time: &str) -> Result<Duration, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The commandline args this fuzzer accepts
|
/// The commandline args this fuzzer accepts
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, Parser)]
|
||||||
#[clap(
|
#[command(
|
||||||
name = "libfuzzer_libpng_launcher",
|
name = "libfuzzer_libpng_launcher",
|
||||||
about = "A libfuzzer-like fuzzer for libpng with llmp-multithreading support and a launcher",
|
about = "A libfuzzer-like fuzzer for libpng with llmp-multithreading support and a launcher",
|
||||||
author = "Andrea Fioraldi <andreafioraldi@gmail.com>, Dominik Maier <domenukk@gmail.com>"
|
author = "Andrea Fioraldi <andreafioraldi@gmail.com>, Dominik Maier <domenukk@gmail.com>"
|
||||||
)]
|
)]
|
||||||
struct Opt {
|
struct Opt {
|
||||||
#[clap(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
parse(try_from_str = Cores::from_cmdline),
|
value_parser = Cores::from_cmdline,
|
||||||
help = "Spawn a client in each of the provided cores. Broker runs in the 0th core. 'all' to select all available cores. 'none' to run a client without binding to any core. eg: '1,2-4,6' selects the cores 1,2,3,4,6.",
|
help = "Spawn a client in each of the provided cores. Broker runs in the 0th core. 'all' to select all available cores. 'none' to run a client without binding to any core. eg: '1,2-4,6' selects the cores 1,2,3,4,6.",
|
||||||
name = "CORES"
|
name = "CORES"
|
||||||
)]
|
)]
|
||||||
cores: Cores,
|
cores: Cores,
|
||||||
|
|
||||||
#[clap(
|
#[arg(
|
||||||
short = 'p',
|
short = 'p',
|
||||||
long,
|
long,
|
||||||
help = "Choose the broker TCP port, default is 1337",
|
help = "Choose the broker TCP port, default is 1337",
|
||||||
@ -73,47 +73,34 @@ struct Opt {
|
|||||||
)]
|
)]
|
||||||
broker_port: u16,
|
broker_port: u16,
|
||||||
|
|
||||||
#[clap(
|
#[arg(short = 'a', long, help = "Specify a remote broker", name = "REMOTE")]
|
||||||
parse(try_from_str),
|
|
||||||
short = 'a',
|
|
||||||
long,
|
|
||||||
help = "Specify a remote broker",
|
|
||||||
name = "REMOTE"
|
|
||||||
)]
|
|
||||||
remote_broker_addr: Option<SocketAddr>,
|
remote_broker_addr: Option<SocketAddr>,
|
||||||
|
|
||||||
#[clap(
|
#[arg(short, long, help = "Set an initial corpus directory", name = "INPUT")]
|
||||||
parse(try_from_str),
|
|
||||||
short,
|
|
||||||
long,
|
|
||||||
help = "Set an initial corpus directory",
|
|
||||||
name = "INPUT"
|
|
||||||
)]
|
|
||||||
input: Vec<PathBuf>,
|
input: Vec<PathBuf>,
|
||||||
|
|
||||||
#[clap(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
parse(try_from_str),
|
|
||||||
help = "Set the output directory, default is ./out",
|
help = "Set the output directory, default is ./out",
|
||||||
name = "OUTPUT",
|
name = "OUTPUT",
|
||||||
default_value = "./out"
|
default_value = "./out"
|
||||||
)]
|
)]
|
||||||
output: PathBuf,
|
output: PathBuf,
|
||||||
|
|
||||||
#[clap(
|
#[arg(
|
||||||
parse(try_from_str = timeout_from_millis_str),
|
value_parser = timeout_from_millis_str,
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
help = "Set the exeucution timeout in milliseconds, default is 10000",
|
help = "Set the execution timeout in milliseconds, default is 10000",
|
||||||
name = "TIMEOUT",
|
name = "TIMEOUT",
|
||||||
default_value = "10000"
|
default_value = "10000"
|
||||||
)]
|
)]
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
/*
|
/*
|
||||||
/// This fuzzer has hard-coded tokens
|
/// This fuzzer has hard-coded tokens
|
||||||
#[clap(
|
#[arg(
|
||||||
parse(from_os_str),
|
|
||||||
short = "x",
|
short = "x",
|
||||||
long,
|
long,
|
||||||
help = "Feed the fuzzer with an user-specified list of tokens (often called \"dictionary\"",
|
help = "Feed the fuzzer with an user-specified list of tokens (often called \"dictionary\"",
|
||||||
|
@ -23,7 +23,7 @@ libafl = { path = "../../libafl/", features = ["std", "derive", "llmp_compressio
|
|||||||
libafl_targets = { path = "../../libafl_targets/", features = ["libfuzzer"] }
|
libafl_targets = { path = "../../libafl_targets/", features = ["libfuzzer"] }
|
||||||
# TODO Include it only when building cc
|
# TODO Include it only when building cc
|
||||||
libafl_cc = { path = "../../libafl_cc/" }
|
libafl_cc = { path = "../../libafl_cc/" }
|
||||||
clap = { version = "3.2", features = ["derive"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
mimalloc = { version = "*", default-features = false }
|
mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
@ -9,7 +9,7 @@ static GLOBAL: MiMalloc = MiMalloc;
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use std::{env, net::SocketAddr, path::PathBuf};
|
use std::{env, net::SocketAddr, path::PathBuf};
|
||||||
|
|
||||||
use clap::{self, StructOpt};
|
use clap::{self, Parser};
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{
|
bolts::{
|
||||||
core_affinity::Cores,
|
core_affinity::Cores,
|
||||||
@ -44,23 +44,23 @@ fn timeout_from_millis_str(time: &str) -> Result<Duration, Error> {
|
|||||||
Ok(Duration::from_millis(time.parse()?))
|
Ok(Duration::from_millis(time.parse()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, Parser)]
|
||||||
#[clap(
|
#[command(
|
||||||
name = "libfuzzer_libpng_ctx",
|
name = "libfuzzer_libpng_ctx",
|
||||||
about = "A clone of libfuzzer using LibAFL for a libpng harness",
|
about = "A clone of libfuzzer using LibAFL for a libpng harness",
|
||||||
author = "Andrea Fioraldi <andreafioraldi@gmail.com>, Dominik Maier <domenukk@gmail.com>"
|
author = "Andrea Fioraldi <andreafioraldi@gmail.com>, Dominik Maier <domenukk@gmail.com>"
|
||||||
)]
|
)]
|
||||||
struct Opt {
|
struct Opt {
|
||||||
#[clap(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
parse(try_from_str = Cores::from_cmdline),
|
value_parser = Cores::from_cmdline,
|
||||||
help = "Spawn a client in each of the provided cores. Broker runs in the 0th core. 'all' to select all available cores. 'none' to run a client without binding to any core. eg: '1,2-4,6' selects the cores 1,2,3,4,6.",
|
help = "Spawn a client in each of the provided cores. Broker runs in the 0th core. 'all' to select all available cores. 'none' to run a client without binding to any core. eg: '1,2-4,6' selects the cores 1,2,3,4,6.",
|
||||||
name = "CORES"
|
name = "CORES"
|
||||||
)]
|
)]
|
||||||
cores: Cores,
|
cores: Cores,
|
||||||
|
|
||||||
#[clap(
|
#[arg(
|
||||||
short = 'p',
|
short = 'p',
|
||||||
long,
|
long,
|
||||||
help = "Choose the broker TCP port, default is 1337",
|
help = "Choose the broker TCP port, default is 1337",
|
||||||
@ -69,38 +69,25 @@ struct Opt {
|
|||||||
)]
|
)]
|
||||||
broker_port: u16,
|
broker_port: u16,
|
||||||
|
|
||||||
#[clap(
|
#[arg(short = 'a', long, help = "Specify a remote broker", name = "REMOTE")]
|
||||||
parse(try_from_str),
|
|
||||||
short = 'a',
|
|
||||||
long,
|
|
||||||
help = "Specify a remote broker",
|
|
||||||
name = "REMOTE"
|
|
||||||
)]
|
|
||||||
remote_broker_addr: Option<SocketAddr>,
|
remote_broker_addr: Option<SocketAddr>,
|
||||||
|
|
||||||
#[clap(
|
#[arg(short, long, help = "Set an initial corpus directory", name = "INPUT")]
|
||||||
parse(try_from_str),
|
|
||||||
short,
|
|
||||||
long,
|
|
||||||
help = "Set an initial corpus directory",
|
|
||||||
name = "INPUT"
|
|
||||||
)]
|
|
||||||
input: Vec<PathBuf>,
|
input: Vec<PathBuf>,
|
||||||
|
|
||||||
#[clap(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
parse(try_from_str),
|
|
||||||
help = "Set the output directory, default is ./out",
|
help = "Set the output directory, default is ./out",
|
||||||
name = "OUTPUT",
|
name = "OUTPUT",
|
||||||
default_value = "./out"
|
default_value = "./out"
|
||||||
)]
|
)]
|
||||||
output: PathBuf,
|
output: PathBuf,
|
||||||
|
|
||||||
#[clap(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
parse(try_from_str = timeout_from_millis_str),
|
value_parser = timeout_from_millis_str,
|
||||||
help = "Set the exeucution timeout in milliseconds, default is 10000",
|
help = "Set the exeucution timeout in milliseconds, default is 10000",
|
||||||
name = "TIMEOUT",
|
name = "TIMEOUT",
|
||||||
default_value = "10000",
|
default_value = "10000",
|
||||||
@ -108,8 +95,8 @@ struct Opt {
|
|||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
/*
|
/*
|
||||||
// The tokens are hardcoded in this example.
|
// The tokens are hardcoded in this example.
|
||||||
#[clap(
|
#[arg(
|
||||||
parse(from_os_str),
|
|
||||||
short = "x",
|
short = "x",
|
||||||
long,
|
long,
|
||||||
help = "Feed the fuzzer with an user-specified list of tokens (often called \"dictionary\"",
|
help = "Feed the fuzzer with an user-specified list of tokens (often called \"dictionary\"",
|
||||||
|
@ -23,7 +23,7 @@ libafl = { path = "../../libafl/", features = ["std", "derive", "llmp_compressio
|
|||||||
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer"] }
|
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "libfuzzer"] }
|
||||||
# TODO Include it only when building cc
|
# TODO Include it only when building cc
|
||||||
libafl_cc = { path = "../../libafl_cc/" }
|
libafl_cc = { path = "../../libafl_cc/" }
|
||||||
clap = { version = "3.2", features = ["derive"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
mimalloc = { version = "*", default-features = false }
|
mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
@ -9,7 +9,7 @@ static GLOBAL: MiMalloc = MiMalloc;
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use std::{env, net::SocketAddr, path::PathBuf};
|
use std::{env, net::SocketAddr, path::PathBuf};
|
||||||
|
|
||||||
use clap::{self, StructOpt};
|
use clap::{self, Parser};
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{
|
bolts::{
|
||||||
core_affinity::Cores,
|
core_affinity::Cores,
|
||||||
@ -46,23 +46,23 @@ fn timeout_from_millis_str(time: &str) -> Result<Duration, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The commandline args this fuzzer accepts
|
/// The commandline args this fuzzer accepts
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, Parser)]
|
||||||
#[clap(
|
#[command(
|
||||||
name = "libfuzzer_libpng_launcher",
|
name = "libfuzzer_libpng_launcher",
|
||||||
about = "A libfuzzer-like fuzzer for libpng with llmp-multithreading support and a launcher",
|
about = "A libfuzzer-like fuzzer for libpng with llmp-multithreading support and a launcher",
|
||||||
author = "Andrea Fioraldi <andreafioraldi@gmail.com>, Dominik Maier <domenukk@gmail.com>"
|
author = "Andrea Fioraldi <andreafioraldi@gmail.com>, Dominik Maier <domenukk@gmail.com>"
|
||||||
)]
|
)]
|
||||||
struct Opt {
|
struct Opt {
|
||||||
#[clap(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
parse(try_from_str = Cores::from_cmdline),
|
value_parser = Cores::from_cmdline,
|
||||||
help = "Spawn a client in each of the provided cores. Broker runs in the 0th core. 'all' to select all available cores. 'none' to run a client without binding to any core. eg: '1,2-4,6' selects the cores 1,2,3,4,6.",
|
help = "Spawn a client in each of the provided cores. Broker runs in the 0th core. 'all' to select all available cores. 'none' to run a client without binding to any core. eg: '1,2-4,6' selects the cores 1,2,3,4,6.",
|
||||||
name = "CORES"
|
name = "CORES"
|
||||||
)]
|
)]
|
||||||
cores: Cores,
|
cores: Cores,
|
||||||
|
|
||||||
#[clap(
|
#[arg(
|
||||||
short = 'p',
|
short = 'p',
|
||||||
long,
|
long,
|
||||||
help = "Choose the broker TCP port, default is 1337",
|
help = "Choose the broker TCP port, default is 1337",
|
||||||
@ -71,36 +71,23 @@ struct Opt {
|
|||||||
)]
|
)]
|
||||||
broker_port: u16,
|
broker_port: u16,
|
||||||
|
|
||||||
#[clap(
|
#[arg(short = 'a', long, help = "Specify a remote broker", name = "REMOTE")]
|
||||||
parse(try_from_str),
|
|
||||||
short = 'a',
|
|
||||||
long,
|
|
||||||
help = "Specify a remote broker",
|
|
||||||
name = "REMOTE"
|
|
||||||
)]
|
|
||||||
remote_broker_addr: Option<SocketAddr>,
|
remote_broker_addr: Option<SocketAddr>,
|
||||||
|
|
||||||
#[clap(
|
#[arg(short, long, help = "Set an initial corpus directory", name = "INPUT")]
|
||||||
parse(try_from_str),
|
|
||||||
short,
|
|
||||||
long,
|
|
||||||
help = "Set an initial corpus directory",
|
|
||||||
name = "INPUT"
|
|
||||||
)]
|
|
||||||
input: Vec<PathBuf>,
|
input: Vec<PathBuf>,
|
||||||
|
|
||||||
#[clap(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
parse(try_from_str),
|
|
||||||
help = "Set the output directory, default is ./out",
|
help = "Set the output directory, default is ./out",
|
||||||
name = "OUTPUT",
|
name = "OUTPUT",
|
||||||
default_value = "./out"
|
default_value = "./out"
|
||||||
)]
|
)]
|
||||||
output: PathBuf,
|
output: PathBuf,
|
||||||
|
|
||||||
#[clap(
|
#[arg(
|
||||||
parse(try_from_str = timeout_from_millis_str),
|
value_parser = timeout_from_millis_str,
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
help = "Set the exeucution timeout in milliseconds, default is 10000",
|
help = "Set the exeucution timeout in milliseconds, default is 10000",
|
||||||
@ -110,8 +97,8 @@ struct Opt {
|
|||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
/*
|
/*
|
||||||
/// This fuzzer has hard-coded tokens
|
/// This fuzzer has hard-coded tokens
|
||||||
#[clap(
|
#[arg(
|
||||||
parse(from_os_str),
|
|
||||||
short = "x",
|
short = "x",
|
||||||
long,
|
long,
|
||||||
help = "Feed the fuzzer with an user-specified list of tokens (often called \"dictionary\"",
|
help = "Feed the fuzzer with an user-specified list of tokens (often called \"dictionary\"",
|
||||||
|
@ -18,7 +18,7 @@ debug = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = { path = "../../../libafl/", features = ["concolic_mutation"] }
|
libafl = { path = "../../../libafl/", features = ["concolic_mutation"] }
|
||||||
libafl_targets = { path = "../../../libafl_targets/", features = ["sancov_pcguard_edges", "sancov_cmplog", "libfuzzer"] }
|
libafl_targets = { path = "../../../libafl_targets/", features = ["sancov_pcguard_edges", "sancov_cmplog", "libfuzzer"] }
|
||||||
clap = { version = "3.2", features = ["derive"]}
|
clap = { version = "4.0", features = ["derive"]}
|
||||||
mimalloc = { version = "*", default-features = false }
|
mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
@ -4,7 +4,7 @@ use mimalloc::MiMalloc;
|
|||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static GLOBAL: MiMalloc = MiMalloc;
|
static GLOBAL: MiMalloc = MiMalloc;
|
||||||
|
|
||||||
use clap::{self, StructOpt};
|
use clap::{self, Parser};
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
@ -54,10 +54,10 @@ use libafl_targets::{
|
|||||||
MAX_EDGES_NUM,
|
MAX_EDGES_NUM,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, Parser)]
|
||||||
struct Opt {
|
struct Opt {
|
||||||
/// This node should do concolic tracing + solving instead of traditional fuzzing
|
/// This node should do concolic tracing + solving instead of traditional fuzzing
|
||||||
#[clap(short, long)]
|
#[arg(short, long)]
|
||||||
concolic: bool,
|
concolic: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ fork = [] # uses the fork() syscall to spawn children, instead of launching a ne
|
|||||||
rand_trait = ["rand_core"] # If set, libafl's rand implementations will implement `rand::Rng`
|
rand_trait = ["rand_core"] # If set, libafl's rand implementations will implement `rand::Rng`
|
||||||
introspection = [] # Include performance statistics of the fuzzing pipeline
|
introspection = [] # Include performance statistics of the fuzzing pipeline
|
||||||
concolic_mutation = ["z3"] # include a simple concolic mutator based on z3
|
concolic_mutation = ["z3"] # include a simple concolic mutator based on z3
|
||||||
python = ["pyo3"]
|
python = ["pyo3", "concat-idents"]
|
||||||
prelude = [] # Expose libafl::prelude for access without additional using directives
|
prelude = [] # Expose libafl::prelude for access without additional using directives
|
||||||
tui_monitor = ["tui", "crossterm"] # enable TuiMonitor with crossterm
|
tui_monitor = ["tui", "crossterm"] # enable TuiMonitor with crossterm
|
||||||
cli = ["clap"] # expose bolts::cli
|
cli = ["clap"] # expose bolts::cli
|
||||||
@ -45,7 +45,7 @@ rustversion = "1.0"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
|
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
|
||||||
serial_test = "0.8"
|
serial_test = "0.9"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl_derive = { version = "0.8.2", optional = true, path = "../libafl_derive" }
|
libafl_derive = { version = "0.8.2", optional = true, path = "../libafl_derive" }
|
||||||
@ -62,47 +62,46 @@ bincode = {version = "1.3", optional = true }
|
|||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
num_enum = { version = "0.5.7", default-features = false }
|
num_enum = { version = "0.5.7", default-features = false }
|
||||||
typed-builder = "0.10.0" # Implement the builder pattern at compiletime
|
typed-builder = "0.10.0" # Implement the builder pattern at compiletime
|
||||||
ahash = { version = "0.7", default-features=false, features=["compile-time-rng"] } # The hash function already used in hashbrown
|
ahash = { version = "0.7", default-features=false } # The hash function already used in hashbrown
|
||||||
intervaltree = { version = "0.2.7", default-features = false, features = ["serde"] }
|
intervaltree = { version = "0.2.7", default-features = false, features = ["serde"] }
|
||||||
backtrace = {version = "0.3", optional = true} # Used to get the stacktrace in StacktraceObserver
|
backtrace = {version = "0.3", optional = true} # Used to get the stacktrace in StacktraceObserver
|
||||||
|
|
||||||
ctor = { optional = true, version = "0.1" }
|
ctor = { optional = true, version = "0.1" }
|
||||||
serde_json = { version = "1.0", optional = true, default-features = false, features = ["alloc"] }
|
serde_json = { version = "1.0", optional = true, default-features = false, features = ["alloc"] }
|
||||||
miniz_oxide = { version = "0.5.3", optional = true}
|
miniz_oxide = { version = "0.6.2", optional = true}
|
||||||
hostname = { version = "^0.3", optional = true } # Is there really no gethostname in the stdlib?
|
hostname = { version = "^0.3", optional = true } # Is there really no gethostname in the stdlib?
|
||||||
rand_core = { version = "0.6", optional = true }
|
rand_core = { version = "0.6", optional = true }
|
||||||
nix = { version = "0.24", optional = true }
|
nix = { version = "0.25", optional = true }
|
||||||
regex = { version = "1", optional = true }
|
regex = { version = "1", optional = true }
|
||||||
uuid = { version = "1.1.2", optional = true, features = ["serde", "v4"] }
|
uuid = { version = "1.1.2", optional = true, features = ["serde", "v4"] }
|
||||||
byteorder = { version = "1.4", optional = true }
|
byteorder = { version = "1.4", optional = true }
|
||||||
once_cell = { version = "1.13", optional = true }
|
once_cell = { version = "1.13", optional = true }
|
||||||
libm = "0.2.2"
|
libm = "0.2.2"
|
||||||
tui = { version = "0.18", default-features = false, features = ['crossterm'], optional = true }
|
tui = { version = "0.19", default-features = false, features = ['crossterm'], optional = true }
|
||||||
crossterm = { version = "0.24", optional = true }
|
crossterm = { version = "0.25", optional = true }
|
||||||
clap = {version = "3.2", features = ["derive", "wrap_help"], optional = true}
|
clap = {version = "4.0", features = ["derive", "wrap_help"], optional = true}
|
||||||
|
|
||||||
wait-timeout = { version = "0.2", optional = true } # used by CommandExecutor to wait for child process
|
wait-timeout = { version = "0.2", optional = true } # used by CommandExecutor to wait for child process
|
||||||
|
|
||||||
z3 = { version = "0.11", features = ["static-link-z3"], optional = true } # for concolic mutation
|
z3 = { version = "0.11", features = ["static-link-z3"], optional = true } # for concolic mutation
|
||||||
|
|
||||||
pyo3 = { version = "0.15", optional = true, features = ["serde", "macros"] }
|
pyo3 = { version = "0.17", optional = true, features = ["serde", "macros"] }
|
||||||
concat-idents = "1.1.3"
|
concat-idents = { version = "1.1.3", optional = true }
|
||||||
|
|
||||||
# AGPL
|
# AGPL
|
||||||
# !!! this create requires nightly
|
# !!! this create requires nightly
|
||||||
grammartec = { version = "0.1", optional = true }
|
grammartec = { version = "0.2", optional = true }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libc = "0.2" # For (*nix) libc
|
libc = "0.2" # For (*nix) libc
|
||||||
uds = "0.2.6"
|
uds = "0.2.6"
|
||||||
lock_api = "0.4.7"
|
lock_api = "0.4.7"
|
||||||
regex = "1"
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
windows = { version = "0.39.0", features = ["Win32_Foundation", "Win32_System_Threading", "Win32_System_Diagnostics_Debug", "Win32_System_Kernel", "Win32_System_Memory", "Win32_Security", "Win32_System_SystemInformation"] }
|
windows = { version = "0.42.0", features = ["Win32_Foundation", "Win32_System_Threading", "Win32_System_Diagnostics_Debug", "Win32_System_Kernel", "Win32_System_Memory", "Win32_Security", "Win32_System_SystemInformation"] }
|
||||||
|
|
||||||
[target.'cfg(windows)'.build-dependencies]
|
[target.'cfg(windows)'.build-dependencies]
|
||||||
windows = "0.39.0"
|
windows = "0.42.0"
|
||||||
|
|
||||||
#[profile.release]
|
#[profile.release]
|
||||||
#lto = true
|
#lto = true
|
||||||
|
@ -106,7 +106,7 @@ fn parse_instrumentation_location(
|
|||||||
|
|
||||||
/// Top-level container for cli options/arguments/subcommands
|
/// Top-level container for cli options/arguments/subcommands
|
||||||
#[derive(Parser, Clone, Debug, Serialize, Deserialize)]
|
#[derive(Parser, Clone, Debug, Serialize, Deserialize)]
|
||||||
#[clap(
|
#[command(
|
||||||
arg_required_else_help(true),
|
arg_required_else_help(true),
|
||||||
subcommand_precedence_over_arg(true),
|
subcommand_precedence_over_arg(true),
|
||||||
args_conflicts_with_subcommands(true)
|
args_conflicts_with_subcommands(true)
|
||||||
@ -114,48 +114,48 @@ fn parse_instrumentation_location(
|
|||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct FuzzerOptions {
|
pub struct FuzzerOptions {
|
||||||
/// timeout for each target execution (milliseconds)
|
/// timeout for each target execution (milliseconds)
|
||||||
#[clap(short, long, default_value = "1000", parse(try_from_str = parse_timeout), help_heading = "Fuzz Options")]
|
#[arg(short, long, default_value = "1000", value_parser = parse_timeout, help_heading = "Fuzz Options")]
|
||||||
pub timeout: Duration,
|
pub timeout: Duration,
|
||||||
|
|
||||||
/// whether or not to print debug info
|
/// whether or not to print debug info
|
||||||
#[clap(short, long)]
|
#[arg(short, long)]
|
||||||
pub verbose: bool,
|
pub verbose: bool,
|
||||||
|
|
||||||
/// file to which all client output should be written
|
/// file to which all client output should be written
|
||||||
#[clap(short, long, default_value = "/dev/null")]
|
#[arg(short, long, default_value = "/dev/null")]
|
||||||
pub stdout: String,
|
pub stdout: String,
|
||||||
|
|
||||||
/// the name of the configuration to use
|
/// the name of the configuration to use
|
||||||
#[clap(long, default_value = "default configuration")]
|
#[arg(long, default_value = "default configuration")]
|
||||||
pub configuration: String,
|
pub configuration: String,
|
||||||
|
|
||||||
/// enable Address Sanitizer (ASAN)
|
/// enable Address Sanitizer (ASAN)
|
||||||
#[clap(short = 'A', long, help_heading = "Fuzz Options")]
|
#[arg(short = 'A', long, help_heading = "Fuzz Options")]
|
||||||
pub asan: bool,
|
pub asan: bool,
|
||||||
|
|
||||||
/// Enable ASAN on each of the provided cores. Use 'all' to select all available
|
/// Enable ASAN on each of the provided cores. Use 'all' to select all available
|
||||||
/// cores. 'none' to run a client without binding to any core.
|
/// cores. 'none' to run a client without binding to any core.
|
||||||
/// ex: '1,2-4,6' selects the cores 1, 2, 3, 4, and 6.
|
/// ex: '1,2-4,6' selects the cores 1, 2, 3, 4, and 6.
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(long, default_value = "0", parse(try_from_str = Cores::from_cmdline), help_heading = "ASAN Options")]
|
#[arg(long, default_value = "0", value_parser = Cores::from_cmdline, help_heading = "ASAN Options")]
|
||||||
pub asan_cores: Cores,
|
pub asan_cores: Cores,
|
||||||
|
|
||||||
/// number of fuzz iterations to perform
|
/// number of fuzz iterations to perform
|
||||||
#[clap(short = 'I', long, help_heading = "Fuzz Options", default_value = "0")]
|
#[arg(short = 'I', long, help_heading = "Fuzz Options", default_value = "0")]
|
||||||
pub iterations: usize,
|
pub iterations: usize,
|
||||||
|
|
||||||
/// path to the harness
|
/// path to the harness
|
||||||
#[clap(short = 'H', long, parse(from_os_str), help_heading = "Fuzz Options")]
|
#[arg(short = 'H', long, help_heading = "Fuzz Options")]
|
||||||
pub harness: Option<PathBuf>,
|
pub harness: Option<PathBuf>,
|
||||||
|
|
||||||
/// trailing arguments (after "--"); can be passed directly to the harness
|
/// trailing arguments (after "--"); can be passed directly to the harness
|
||||||
#[cfg(not(feature = "qemu_cli"))]
|
#[cfg(not(feature = "qemu_cli"))]
|
||||||
#[clap(last = true, name = "HARNESS_ARGS")]
|
#[arg(last = true, value_name = "HARNESS_ARGS")]
|
||||||
pub harness_args: Vec<String>,
|
pub harness_args: Vec<String>,
|
||||||
|
|
||||||
/// harness function to call
|
/// harness function to call
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(
|
#[arg(
|
||||||
short = 'F',
|
short = 'F',
|
||||||
long,
|
long,
|
||||||
default_value = "LLVMFuzzerTestOneInput",
|
default_value = "LLVMFuzzerTestOneInput",
|
||||||
@ -165,17 +165,17 @@ pub struct FuzzerOptions {
|
|||||||
|
|
||||||
/// additional libraries to instrument
|
/// additional libraries to instrument
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(short, long, help_heading = "Frida Options")]
|
#[arg(short, long, help_heading = "Frida Options")]
|
||||||
pub libs_to_instrument: Vec<String>,
|
pub libs_to_instrument: Vec<String>,
|
||||||
|
|
||||||
/// enable CmpLog instrumentation
|
/// enable CmpLog instrumentation
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "frida_cli",
|
feature = "frida_cli",
|
||||||
clap(short = 'C', long, help_heading = "Frida Options")
|
arg(short = 'C', long, help_heading = "Frida Options")
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
not(feature = "frida_cli"),
|
not(feature = "frida_cli"),
|
||||||
clap(short = 'C', long, help_heading = "Fuzz Options")
|
arg(short = 'C', long, help_heading = "Fuzz Options")
|
||||||
)]
|
)]
|
||||||
pub cmplog: bool,
|
pub cmplog: bool,
|
||||||
|
|
||||||
@ -183,27 +183,27 @@ pub struct FuzzerOptions {
|
|||||||
/// cores. 'none' to run a client without binding to any core.
|
/// cores. 'none' to run a client without binding to any core.
|
||||||
/// ex: '1,2-4,6' selects the cores 1, 2, 3, 4, and 6.
|
/// ex: '1,2-4,6' selects the cores 1, 2, 3, 4, and 6.
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(long, default_value = "0", parse(try_from_str = Cores::from_cmdline), help_heading = "Frida Options")]
|
#[arg(long, default_value = "0", value_parser = Cores::from_cmdline, help_heading = "Frida Options")]
|
||||||
pub cmplog_cores: Cores,
|
pub cmplog_cores: Cores,
|
||||||
|
|
||||||
/// enable ASAN leak detection
|
/// enable ASAN leak detection
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(short, long, help_heading = "ASAN Options")]
|
#[arg(short, long, help_heading = "ASAN Options")]
|
||||||
pub detect_leaks: bool,
|
pub detect_leaks: bool,
|
||||||
|
|
||||||
/// instruct ASAN to continue after a memory error is detected
|
/// instruct ASAN to continue after a memory error is detected
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(long, help_heading = "ASAN Options")]
|
#[arg(long, help_heading = "ASAN Options")]
|
||||||
pub continue_on_error: bool,
|
pub continue_on_error: bool,
|
||||||
|
|
||||||
/// instruct ASAN to gather (and report) allocation-/free-site backtraces
|
/// instruct ASAN to gather (and report) allocation-/free-site backtraces
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(long, help_heading = "ASAN Options")]
|
#[arg(long, help_heading = "ASAN Options")]
|
||||||
pub allocation_backtraces: bool,
|
pub allocation_backtraces: bool,
|
||||||
|
|
||||||
/// the maximum size that the ASAN allocator should allocate
|
/// the maximum size that the ASAN allocator should allocate
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
default_value = "1073741824", // 1_usize << 30
|
default_value = "1073741824", // 1_usize << 30
|
||||||
@ -213,7 +213,7 @@ pub struct FuzzerOptions {
|
|||||||
|
|
||||||
/// the maximum total allocation size that the ASAN allocator should allocate
|
/// the maximum total allocation size that the ASAN allocator should allocate
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(
|
#[arg(
|
||||||
short = 'M',
|
short = 'M',
|
||||||
long,
|
long,
|
||||||
default_value = "4294967296", // 1_usize << 32
|
default_value = "4294967296", // 1_usize << 32
|
||||||
@ -223,56 +223,47 @@ pub struct FuzzerOptions {
|
|||||||
|
|
||||||
/// instruct ASAN to panic if the max ASAN allocation size is exceeded
|
/// instruct ASAN to panic if the max ASAN allocation size is exceeded
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(long, help_heading = "ASAN Options")]
|
#[arg(long, help_heading = "ASAN Options")]
|
||||||
pub max_allocation_panics: bool,
|
pub max_allocation_panics: bool,
|
||||||
|
|
||||||
/// disable coverage
|
/// disable coverage
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(long, help_heading = "Frida Options")]
|
#[arg(long, help_heading = "Frida Options")]
|
||||||
pub disable_coverage: bool,
|
pub disable_coverage: bool,
|
||||||
|
|
||||||
/// enable DrCov (aarch64 only)
|
/// enable DrCov (aarch64 only)
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(long, help_heading = "Frida Options")]
|
#[arg(long, help_heading = "Frida Options")]
|
||||||
pub drcov: bool,
|
pub drcov: bool,
|
||||||
|
|
||||||
/// locations which will not be instrumented for ASAN or coverage purposes (ex: mod_name@0x12345)
|
/// locations which will not be instrumented for ASAN or coverage purposes (ex: mod_name@0x12345)
|
||||||
#[cfg(feature = "frida_cli")]
|
#[cfg(feature = "frida_cli")]
|
||||||
#[clap(short = 'D', long, help_heading = "Frida Options", parse(try_from_str = parse_instrumentation_location), multiple_occurrences = true)]
|
#[arg(short = 'D', long, help_heading = "Frida Options", value_parser = parse_instrumentation_location)]
|
||||||
pub dont_instrument: Vec<(String, usize)>,
|
pub dont_instrument: Vec<(String, usize)>,
|
||||||
|
|
||||||
/// trailing arguments (after "--"); can be passed directly to QEMU
|
/// trailing arguments (after "--"); can be passed directly to QEMU
|
||||||
#[cfg(feature = "qemu_cli")]
|
#[cfg(feature = "qemu_cli")]
|
||||||
#[clap(last = true)]
|
#[arg(last = true)]
|
||||||
pub qemu_args: Vec<String>,
|
pub qemu_args: Vec<String>,
|
||||||
|
|
||||||
/// paths to fuzzer token files (aka 'dictionaries')
|
/// paths to fuzzer token files (aka 'dictionaries')
|
||||||
#[clap(
|
#[arg(short = 'x', long, help_heading = "Fuzz Options")]
|
||||||
short = 'x',
|
|
||||||
long,
|
|
||||||
multiple_values = true,
|
|
||||||
parse(from_os_str),
|
|
||||||
help_heading = "Fuzz Options"
|
|
||||||
)]
|
|
||||||
pub tokens: Vec<PathBuf>,
|
pub tokens: Vec<PathBuf>,
|
||||||
|
|
||||||
/// input corpus directories
|
/// input corpus directories
|
||||||
#[clap(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
default_values = &["corpus/"],
|
default_values = &["corpus/"],
|
||||||
multiple_values = true,
|
|
||||||
parse(from_os_str),
|
|
||||||
help_heading = "Corpus Options"
|
help_heading = "Corpus Options"
|
||||||
)]
|
)]
|
||||||
pub input: Vec<PathBuf>,
|
pub input: Vec<PathBuf>,
|
||||||
|
|
||||||
/// output solutions directory
|
/// output solutions directory
|
||||||
#[clap(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
default_value = "solutions/",
|
default_value = "solutions/",
|
||||||
parse(from_os_str),
|
|
||||||
help_heading = "Corpus Options"
|
help_heading = "Corpus Options"
|
||||||
)]
|
)]
|
||||||
pub output: PathBuf,
|
pub output: PathBuf,
|
||||||
@ -280,27 +271,26 @@ pub struct FuzzerOptions {
|
|||||||
/// Spawn a client in each of the provided cores. Use 'all' to select all available
|
/// Spawn a client in each of the provided cores. Use 'all' to select all available
|
||||||
/// cores. 'none' to run a client without binding to any core.
|
/// cores. 'none' to run a client without binding to any core.
|
||||||
/// ex: '1,2-4,6' selects the cores 1, 2, 3, 4, and 6.
|
/// ex: '1,2-4,6' selects the cores 1, 2, 3, 4, and 6.
|
||||||
#[clap(short = 'c', long, default_value = "0", parse(try_from_str = Cores::from_cmdline))]
|
#[arg(short = 'c', long, default_value = "0", value_parser = Cores::from_cmdline)]
|
||||||
pub cores: Cores,
|
pub cores: Cores,
|
||||||
|
|
||||||
/// port on which the broker should listen
|
/// port on which the broker should listen
|
||||||
#[clap(short = 'p', long, default_value = "1337", name = "PORT")]
|
#[arg(short = 'p', long, default_value = "1337", value_name = "PORT")]
|
||||||
pub broker_port: u16,
|
pub broker_port: u16,
|
||||||
|
|
||||||
/// ip:port where a remote broker is already listening
|
/// ip:port where a remote broker is already listening
|
||||||
#[clap(short = 'a', long, parse(try_from_str), name = "REMOTE")]
|
#[arg(short = 'a', long, value_name = "REMOTE")]
|
||||||
pub remote_broker_addr: Option<SocketAddr>,
|
pub remote_broker_addr: Option<SocketAddr>,
|
||||||
|
|
||||||
/// path to file that should be sent to the harness for crash reproduction
|
/// path to file that should be sent to the harness for crash reproduction
|
||||||
#[clap(short, long, parse(from_os_str), help_heading = "Replay Options")]
|
#[arg(short, long, help_heading = "Replay Options")]
|
||||||
pub replay: Option<PathBuf>,
|
pub replay: Option<PathBuf>,
|
||||||
|
|
||||||
/// Run the same replay input multiple times
|
/// Run the same replay input multiple times
|
||||||
#[clap(
|
#[arg(
|
||||||
short = 'R',
|
short = 'R',
|
||||||
long,
|
long,
|
||||||
default_missing_value = "1",
|
default_missing_value = "1",
|
||||||
min_values = 0,
|
|
||||||
help_heading = "Replay Options",
|
help_heading = "Replay Options",
|
||||||
requires = "replay"
|
requires = "replay"
|
||||||
)]
|
)]
|
||||||
@ -319,10 +309,10 @@ impl FuzzerOptions {
|
|||||||
/// fn custom_func(_: &str) {} // not relevant; just for illustrative purposes
|
/// fn custom_func(_: &str) {} // not relevant; just for illustrative purposes
|
||||||
///
|
///
|
||||||
/// #[derive(Parser, Debug)]
|
/// #[derive(Parser, Debug)]
|
||||||
/// #[clap(name = "custom")] // the name of the new subcommand
|
/// #[arg(name = "custom")] // the name of the new subcommand
|
||||||
/// struct CustomFooParser {
|
/// struct CustomFooParser {
|
||||||
/// /// a very cromulent option
|
/// /// a very cromulent option
|
||||||
/// #[clap(short, long)]
|
/// #[arg(short, long)]
|
||||||
/// bar: String,
|
/// bar: String,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
@ -342,7 +332,7 @@ impl FuzzerOptions {
|
|||||||
///
|
///
|
||||||
/// // process the results
|
/// // process the results
|
||||||
/// if let Some(("custom", sub_matches)) = matches.subcommand() {
|
/// if let Some(("custom", sub_matches)) = matches.subcommand() {
|
||||||
/// custom_func(sub_matches.value_of("bar").unwrap())
|
/// custom_func(sub_matches.get_one::<String>("bar").unwrap())
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// println!("{:?}", matches);
|
/// println!("{:?}", matches);
|
||||||
|
@ -384,7 +384,7 @@ mod windows {
|
|||||||
|
|
||||||
let mut outga = GROUP_AFFINITY::default();
|
let mut outga = GROUP_AFFINITY::default();
|
||||||
|
|
||||||
let result = SetThreadGroupAffinity(GetCurrentThread(), &ga, &mut outga);
|
let result = SetThreadGroupAffinity(GetCurrentThread(), &ga, Some(&mut outga));
|
||||||
if result.0 == 0 {
|
if result.0 == 0 {
|
||||||
Err(Error::unknown("Failed to set_for_current"))
|
Err(Error::unknown("Failed to set_for_current"))
|
||||||
} else {
|
} else {
|
||||||
|
@ -443,6 +443,7 @@ pub mod pybind {
|
|||||||
use crate::bolts::{current_nanos, rands::StdRand};
|
use crate::bolts::{current_nanos, rands::StdRand};
|
||||||
|
|
||||||
#[pyclass(unsendable, name = "StdRand")]
|
#[pyclass(unsendable, name = "StdRand")]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
/// Python class for StdRand
|
/// Python class for StdRand
|
||||||
pub struct PythonStdRand {
|
pub struct PythonStdRand {
|
||||||
@ -478,6 +479,7 @@ pub mod pybind {
|
|||||||
|
|
||||||
/// Rand Trait binding
|
/// Rand Trait binding
|
||||||
#[pyclass(unsendable, name = "Rand")]
|
#[pyclass(unsendable, name = "Rand")]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct PythonRand {
|
pub struct PythonRand {
|
||||||
wrapper: PythonRandWrapper,
|
wrapper: PythonRandWrapper,
|
||||||
|
@ -1159,7 +1159,7 @@ pub mod win32_shmem {
|
|||||||
use core::{
|
use core::{
|
||||||
ffi::c_void,
|
ffi::c_void,
|
||||||
fmt::{self, Debug, Formatter},
|
fmt::{self, Debug, Formatter},
|
||||||
ptr, slice,
|
slice,
|
||||||
};
|
};
|
||||||
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
@ -1214,7 +1214,7 @@ pub mod win32_shmem {
|
|||||||
map_str_bytes[19] = 0; // Trucate to size 20
|
map_str_bytes[19] = 0; // Trucate to size 20
|
||||||
let handle = CreateFileMappingA(
|
let handle = CreateFileMappingA(
|
||||||
HANDLE(INVALID_HANDLE_VALUE),
|
HANDLE(INVALID_HANDLE_VALUE),
|
||||||
ptr::null_mut(),
|
None,
|
||||||
PAGE_READWRITE,
|
PAGE_READWRITE,
|
||||||
0,
|
0,
|
||||||
map_size as u32,
|
map_size as u32,
|
||||||
|
@ -150,6 +150,7 @@ pub mod pybind {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[pyclass(unsendable, name = "CachedOnDiskCorpus")]
|
#[pyclass(unsendable, name = "CachedOnDiskCorpus")]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
/// Python class for CachedOnDiskCorpus
|
/// Python class for CachedOnDiskCorpus
|
||||||
pub struct PythonCachedOnDiskCorpus {
|
pub struct PythonCachedOnDiskCorpus {
|
||||||
|
@ -104,6 +104,7 @@ pub mod pybind {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[pyclass(unsendable, name = "InMemoryCorpus")]
|
#[pyclass(unsendable, name = "InMemoryCorpus")]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
/// Python class for InMemoryCorpus
|
/// Python class for InMemoryCorpus
|
||||||
pub struct PythonInMemoryCorpus {
|
pub struct PythonInMemoryCorpus {
|
||||||
|
@ -247,6 +247,7 @@ pub mod pybind {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[pyclass(unsendable, name = "OnDiskCorpus")]
|
#[pyclass(unsendable, name = "OnDiskCorpus")]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
/// Python class for OnDiskCorpus
|
/// Python class for OnDiskCorpus
|
||||||
pub struct PythonOnDiskCorpus {
|
pub struct PythonOnDiskCorpus {
|
||||||
|
@ -205,6 +205,7 @@ pub mod pybind {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[pyclass(unsendable, name = "ExitKind")]
|
#[pyclass(unsendable, name = "ExitKind")]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct PythonExitKind {
|
pub struct PythonExitKind {
|
||||||
pub inner: ExitKind,
|
pub inner: ExitKind,
|
||||||
|
@ -232,8 +232,8 @@ impl<E: HasInProcessHandlers> TimeoutExecutor<E> {
|
|||||||
let tp_timer = unsafe {
|
let tp_timer = unsafe {
|
||||||
CreateThreadpoolTimer(
|
CreateThreadpoolTimer(
|
||||||
Some(timeout_handler),
|
Some(timeout_handler),
|
||||||
addr_of_mut!(GLOBAL_STATE) as *mut c_void,
|
Some(addr_of_mut!(GLOBAL_STATE) as *mut c_void),
|
||||||
&TP_CALLBACK_ENVIRON_V3::default(),
|
Some(&TP_CALLBACK_ENVIRON_V3::default()),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let mut critical = RTL_CRITICAL_SECTION::default();
|
let mut critical = RTL_CRITICAL_SECTION::default();
|
||||||
@ -301,7 +301,7 @@ where
|
|||||||
LeaveCriticalSection(&mut self.critical);
|
LeaveCriticalSection(&mut self.critical);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
SetThreadpoolTimer(self.tp_timer, &ft, 0, 0);
|
SetThreadpoolTimer(self.tp_timer, Some(&ft), 0, 0);
|
||||||
|
|
||||||
let ret = self.executor.run_target(fuzzer, state, mgr, input);
|
let ret = self.executor.run_target(fuzzer, state, mgr, input);
|
||||||
|
|
||||||
@ -326,7 +326,7 @@ where
|
|||||||
/// Will dereference the given `tp_timer` pointer, unchecked.
|
/// Will dereference the given `tp_timer` pointer, unchecked.
|
||||||
fn post_run_reset(&mut self) {
|
fn post_run_reset(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
SetThreadpoolTimer(self.tp_timer, core::ptr::null(), 0, 0);
|
SetThreadpoolTimer(self.tp_timer, None, 0, 0);
|
||||||
}
|
}
|
||||||
self.executor.post_run_reset();
|
self.executor.post_run_reset();
|
||||||
}
|
}
|
||||||
|
@ -2009,6 +2009,7 @@ pub mod pybind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[pyclass(unsendable, name = $py_name2)]
|
#[pyclass(unsendable, name = $py_name2)]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
/// Python class for OwnedMapObserver (i.e. StdMapObserver with owned map)
|
/// Python class for OwnedMapObserver (i.e. StdMapObserver with owned map)
|
||||||
pub struct $struct_name2 {
|
pub struct $struct_name2 {
|
||||||
@ -2079,6 +2080,7 @@ pub mod pybind {
|
|||||||
|
|
||||||
// Should not be exposed to user
|
// Should not be exposed to user
|
||||||
#[pyclass(unsendable, name = $py_name_trait)]
|
#[pyclass(unsendable, name = $py_name_trait)]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
/// MapObserver + Observer Trait binding
|
/// MapObserver + Observer Trait binding
|
||||||
pub struct $struct_name_trait {
|
pub struct $struct_name_trait {
|
||||||
|
@ -458,6 +458,7 @@ pub mod pybind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[pyclass(unsendable, name = "Observer")]
|
#[pyclass(unsendable, name = "Observer")]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
/// Observer Trait binding
|
/// Observer Trait binding
|
||||||
pub struct PythonObserver {
|
pub struct PythonObserver {
|
||||||
@ -797,6 +798,7 @@ pub mod pybind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
#[pyclass(unsendable, name = "ObserversTuple")]
|
#[pyclass(unsendable, name = "ObserversTuple")]
|
||||||
pub struct PythonObserversTuple {
|
pub struct PythonObserversTuple {
|
||||||
list: Vec<PythonObserver>,
|
list: Vec<PythonObserver>,
|
||||||
|
@ -26,7 +26,7 @@ libafl = {path = "../../libafl", version="0.8", default-features=false, features
|
|||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cmake = "0.1"
|
cmake = "0.1"
|
||||||
bindgen = "0.60"
|
bindgen = "0.61"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
which = "4.2"
|
which = "4.2"
|
||||||
|
@ -15,4 +15,4 @@ categories = ["development-tools::testing", "emulators", "embedded", "os", "no-s
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = {path = "../../../libafl"}
|
libafl = {path = "../../../libafl"}
|
||||||
clap = { version = "3.2", features = ["derive"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
|
@ -11,7 +11,7 @@ use std::{
|
|||||||
string::ToString,
|
string::ToString,
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::{self, StructOpt};
|
use clap::{self, Parser};
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{
|
bolts::{
|
||||||
shmem::{ShMem, ShMemProvider, StdShMemProvider},
|
shmem::{ShMem, ShMemProvider, StdShMemProvider},
|
||||||
@ -23,38 +23,38 @@ use libafl::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, Parser)]
|
||||||
#[clap(
|
#[command(
|
||||||
name = "dump_constraints",
|
name = "dump_constraints",
|
||||||
about = "Dump tool for concolic constraints."
|
about = "Dump tool for concolic constraints."
|
||||||
)]
|
)]
|
||||||
struct Opt {
|
struct Opt {
|
||||||
/// Outputs plain text instead of binary
|
/// Outputs plain text instead of binary
|
||||||
#[clap(short, long)]
|
#[arg(short, long)]
|
||||||
plain_text: bool,
|
plain_text: bool,
|
||||||
|
|
||||||
/// Outputs coverage information to the given file
|
/// Outputs coverage information to the given file
|
||||||
#[clap(short, long)]
|
#[arg(short, long)]
|
||||||
coverage_file: Option<PathBuf>,
|
coverage_file: Option<PathBuf>,
|
||||||
|
|
||||||
/// Symbolizes only the given input file offsets.
|
/// Symbolizes only the given input file offsets.
|
||||||
#[clap(short, long)]
|
#[arg(short, long)]
|
||||||
symbolize_offsets: Option<Vec<usize>>,
|
symbolize_offsets: Option<Vec<usize>>,
|
||||||
|
|
||||||
/// Concretize all floating point operations.
|
/// Concretize all floating point operations.
|
||||||
#[clap(long)]
|
#[arg(long)]
|
||||||
no_float: bool,
|
no_float: bool,
|
||||||
|
|
||||||
/// Prune expressions from high-frequency code locations.
|
/// Prune expressions from high-frequency code locations.
|
||||||
#[clap(long)]
|
#[arg(long)]
|
||||||
prune: bool,
|
prune: bool,
|
||||||
|
|
||||||
/// Trace file path, "trace" by default.
|
/// Trace file path, "trace" by default.
|
||||||
#[clap(parse(from_os_str), short, long)]
|
#[arg(short, long)]
|
||||||
output: Option<PathBuf>,
|
output: Option<PathBuf>,
|
||||||
|
|
||||||
/// Target program and arguments
|
/// Target program and arguments
|
||||||
#[clap(last = true)]
|
#[arg(last = true)]
|
||||||
program: Vec<OsString>,
|
program: Vec<OsString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ cc = { version = "1.0", features = ["parallel"] }
|
|||||||
libafl = { path = "../libafl", version = "0.8.2", features = ["std", "libafl_derive", "frida_cli"] }
|
libafl = { path = "../libafl", version = "0.8.2", features = ["std", "libafl_derive", "frida_cli"] }
|
||||||
libafl_targets = { path = "../libafl_targets", version = "0.8.2", features = ["std", "sancov_cmplog"] }
|
libafl_targets = { path = "../libafl_targets", version = "0.8.2", features = ["std", "sancov_cmplog"] }
|
||||||
|
|
||||||
nix = "0.24"
|
nix = "0.25"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
hashbrown = "0.12"
|
hashbrown = "0.12"
|
||||||
libloading = "0.7"
|
libloading = "0.7"
|
||||||
|
@ -15,5 +15,5 @@ categories = ["development-tools::testing", "emulators", "embedded", "os", "no-s
|
|||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
libnyx = {git = "https://github.com/nyx-fuzz/libnyx.git",rev = "acaf7f6"}
|
libnyx = {git = "https://github.com/nyx-fuzz/libnyx.git",rev = "acaf7f6"}
|
||||||
libafl = { path = "../libafl", version = "0.8.0", features = ["std", "libafl_derive", "frida_cli" ]}
|
libafl = { path = "../libafl", version = "0.8.2", features = ["std", "libafl_derive", "frida_cli" ]}
|
||||||
libafl_targets = { path = "../libafl_targets", version = "0.8.0", features = ["std", "sancov_cmplog"] }
|
libafl_targets = { path = "../libafl_targets", version = "0.8.2", features = ["std", "sancov_cmplog"] }
|
||||||
|
@ -44,12 +44,12 @@ bio = "0.41"
|
|||||||
thread_local = "1.1.4"
|
thread_local = "1.1.4"
|
||||||
capstone = "0.11.0"
|
capstone = "0.11.0"
|
||||||
#pyo3 = { version = "0.15", features = ["extension-module"], optional = true }
|
#pyo3 = { version = "0.15", features = ["extension-module"], optional = true }
|
||||||
pyo3 = { version = "0.15", optional = true }
|
pyo3 = { version = "0.17", features = ["pyproto"], optional = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cc = { version = "1.0" }
|
cc = { version = "1.0" }
|
||||||
which = "4.2"
|
which = "4.2"
|
||||||
pyo3-build-config = { version = "0.16", optional = true }
|
pyo3-build-config = { version = "0.15", optional = true }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "libafl_qemu"
|
name = "libafl_qemu"
|
||||||
|
@ -24,7 +24,7 @@ arm = ["libafl_qemu/arm"] # build qemu for arm
|
|||||||
aarch64 = ["libafl_qemu/aarch64"] # build qemu for aarch64
|
aarch64 = ["libafl_qemu/aarch64"] # build qemu for aarch64
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
pyo3-build-config = { version = "0.16", optional = true }
|
pyo3-build-config = { version = "0.15", optional = true }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = { path = "../libafl", version = "0.8.2" }
|
libafl = { path = "../libafl", version = "0.8.2" }
|
||||||
@ -32,8 +32,8 @@ libafl_targets = { path = "../libafl_targets", version = "0.8.2" }
|
|||||||
libafl_qemu = { path = "../libafl_qemu", version = "0.8.2" }
|
libafl_qemu = { path = "../libafl_qemu", version = "0.8.2" }
|
||||||
|
|
||||||
typed-builder = "0.10.0" # Implement the builder pattern at compiletime
|
typed-builder = "0.10.0" # Implement the builder pattern at compiletime
|
||||||
#pyo3 = { version = "0.15", features = ["extension-module"], optional = true }
|
#pyo3 = { version = "0.17", features = ["extension-module"], optional = true }
|
||||||
pyo3 = { version = "0.15", optional = true }
|
pyo3 = { version = "0.17", optional = true }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "libafl_sugar"
|
name = "libafl_sugar"
|
||||||
|
@ -20,4 +20,4 @@ regex = "1"
|
|||||||
postcard = "1.0"
|
postcard = "1.0"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
libafl = { path = "../../../libafl" }
|
libafl = { path = "../../../libafl" }
|
||||||
clap = { version = "3.2", features = ["derive"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
|
@ -6,21 +6,20 @@ use std::{
|
|||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::{self, StructOpt};
|
use clap::{self, Parser};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use libafl::generators::gramatron::{Automaton, Trigger};
|
use libafl::generators::gramatron::{Automaton, Trigger};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, Parser)]
|
||||||
#[clap(
|
#[command(
|
||||||
name = "construct_automata",
|
name = "construct_automata",
|
||||||
about = "Generate a serialized Automaton using a json GNF grammar",
|
about = "Generate a serialized Automaton using a json GNF grammar",
|
||||||
author = "Andrea Fioraldi <andreafioraldi@gmail.com>"
|
author = "Andrea Fioraldi <andreafioraldi@gmail.com>"
|
||||||
)]
|
)]
|
||||||
struct Opt {
|
struct Opt {
|
||||||
#[clap(
|
#[arg(
|
||||||
parse(try_from_str),
|
|
||||||
short,
|
short,
|
||||||
long = "grammar-file",
|
long = "grammar-file",
|
||||||
name = "GRAMMAR",
|
name = "GRAMMAR",
|
||||||
@ -28,8 +27,7 @@ struct Opt {
|
|||||||
)]
|
)]
|
||||||
grammar: PathBuf,
|
grammar: PathBuf,
|
||||||
|
|
||||||
#[clap(
|
#[arg(
|
||||||
parse(try_from_str),
|
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
name = "LIMIT",
|
name = "LIMIT",
|
||||||
@ -38,13 +36,7 @@ struct Opt {
|
|||||||
)]
|
)]
|
||||||
limit: usize,
|
limit: usize,
|
||||||
|
|
||||||
#[clap(
|
#[arg(short, long, help = "Set the output file", name = "OUTPUT")]
|
||||||
parse(try_from_str),
|
|
||||||
short,
|
|
||||||
long,
|
|
||||||
help = "Set the output file",
|
|
||||||
name = "OUTPUT"
|
|
||||||
)]
|
|
||||||
output: PathBuf,
|
output: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||||
name = "libafl_benches"
|
name = "libafl_benches"
|
||||||
version = "0.8.2"
|
version.workspace = true
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "LibAFL Benchmarks"
|
description = "LibAFL Benchmarks"
|
||||||
documentation = "https://docs.rs/libafl"
|
documentation = "https://docs.rs/libafl"
|
||||||
@ -13,7 +13,7 @@ categories = ["development-tools::testing", "emulators", "embedded", "os", "no-s
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.3" # Benchmarking
|
criterion = "0.3" # Benchmarking
|
||||||
ahash = { version = "0.7", default-features=false, features=["compile-time-rng"] } # The hash function already used in hashbrown
|
ahash = { version = "0.7", default-features=false } # The hash function already used in hashbrown
|
||||||
rustc-hash = { version = "1.1", default-features=false } # yet another hash
|
rustc-hash = { version = "1.1", default-features=false } # yet another hash
|
||||||
xxhash-rust = { version = "0.8.5", features = ["xxh3"] } # xxh3 hashing for rust
|
xxhash-rust = { version = "0.8.5", features = ["xxh3"] } # xxh3 hashing for rust
|
||||||
libafl = { path = "../../libafl", default-features=false } # libafl
|
libafl = { path = "../../libafl", default-features=false } # libafl
|
||||||
|
Loading…
x
Reference in New Issue
Block a user