Skip to content

Commit

Permalink
[libcasr] CI fuzzing with cargo-fuzz (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
anfedotoff authored Sep 16, 2023
1 parent c50d011 commit c229bed
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 1 deletion.
17 changes: 17 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ jobs:
cargo install cargo-fuzz
cargo test --release --verbose
ubuntu-fuzz:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Fuzzing
run: |
curl https://sh.rustup.rs -o rustup.sh && chmod +x rustup.sh && \
./rustup.sh -y && rm rustup.sh
rustup install nightly
export PATH=/root/.cargo/bin:$PATH
cargo install cargo-fuzz
cd libcasr/fuzz
mkdir corpus
cargo +nightly fuzz run parse_stacktrace corpus init_corpus -- -max_total_time=600
ubuntu-aarch64:

runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion libcasr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repository = "https://github.com/ispras/casr.git"
documentation = "https://docs.rs/libcasr"
edition = "2021"
license = "Apache-2.0"
exclude = ["/tests"]
exclude = ["/fuzz"]

[dependencies]
regex = "1"
Expand Down
4 changes: 4 additions & 0 deletions libcasr/fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
target
corpus
artifacts
coverage
28 changes: 28 additions & 0 deletions libcasr/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "libcasr-fuzz"
version = "0.1.0"
authors = ["Andrey Fedotov [email protected]"]
publish = false
edition = "2021"

[package.metadata]
cargo-fuzz = true

[dependencies]
libfuzzer-sys = "0.4"

[dependencies.libcasr]
path = ".."

# Prevent this from interfering with workspaces
[workspace]
members = ["."]

[profile.release]
debug = 1

[[bin]]
name = "parse_stacktrace"
path = "fuzz_targets/parse_stacktrace.rs"
test = false
doc = false
73 changes: 73 additions & 0 deletions libcasr/fuzz/fuzz_targets/parse_stacktrace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#![no_main]

use libfuzzer_sys::fuzz_target;

use libcasr::{
asan::AsanStacktrace,
constants::{
STACK_FRAME_FILEPATH_IGNORE_REGEXES_CPP, STACK_FRAME_FILEPATH_IGNORE_REGEXES_GO,
STACK_FRAME_FILEPATH_IGNORE_REGEXES_JAVA, STACK_FRAME_FILEPATH_IGNORE_REGEXES_PYTHON,
STACK_FRAME_FILEPATH_IGNORE_REGEXES_RUST, STACK_FRAME_FUNCTION_IGNORE_REGEXES_CPP,
STACK_FRAME_FUNCTION_IGNORE_REGEXES_GO, STACK_FRAME_FUNCTION_IGNORE_REGEXES_JAVA,
STACK_FRAME_FUNCTION_IGNORE_REGEXES_PYTHON, STACK_FRAME_FUNCTION_IGNORE_REGEXES_RUST,
},
gdb::GdbStacktrace,
go::GoStacktrace,
init_ignored_frames,
java::JavaStacktrace,
python::PythonStacktrace,
stacktrace::{
CrashLineExt, ParseStacktrace, STACK_FRAME_FILEPATH_IGNORE_REGEXES,
STACK_FRAME_FUNCTION_IGNORE_REGEXES,
},
};

fuzz_target!(|data: &[u8]| {
if data.len() < 2 {
return;
}
let s = String::from_utf8_lossy(&data[1..]);
init_ignored_frames!("cpp", "rust", "python", "go", "java");
match data[0] % 5 {
0 => {
// Asan
if let Ok(raw) = AsanStacktrace::extract_stacktrace(&s) {
if let Ok(st) = AsanStacktrace::parse_stacktrace(&raw) {
let _ = st.crash_line();
}
}
}
1 => {
// Go
if let Ok(raw) = GoStacktrace::extract_stacktrace(&s) {
if let Ok(st) = GoStacktrace::parse_stacktrace(&raw) {
let _ = st.crash_line();
}
}
}
2 => {
// Python
if let Ok(raw) = PythonStacktrace::extract_stacktrace(&s) {
if let Ok(st) = PythonStacktrace::parse_stacktrace(&raw) {
let _ = st.crash_line();
}
}
}
3 => {
// Java
if let Ok(raw) = JavaStacktrace::extract_stacktrace(&s) {
if let Ok(st) = JavaStacktrace::parse_stacktrace(&raw) {
let _ = st.crash_line();
}
}
}
_ => {
// Gdb
if let Ok(raw) = GdbStacktrace::extract_stacktrace(&s) {
if let Ok(st) = GdbStacktrace::parse_stacktrace(&raw) {
let _ = st.crash_line();
}
}
}
}
});
Binary file added libcasr/fuzz/init_corpus/asan
Binary file not shown.
9 changes: 9 additions & 0 deletions libcasr/fuzz/init_corpus/gdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
 #0 0x00000000005e3099 in xlnt::detail::compound_document::read_directory (this=0x7fffffffcee0) at /xlnt/source/detail/cryptography/compound_document.cpp:975
#1 0x00000000005e2956 in xlnt::detail::compound_document::compound_document (this=0x7fffffffcee0, in=...) at /xlnt/source/detail/cryptography/compound_document.cpp:517
#2 0x000000000048a45c in (anonymous namespace)::decrypt_xlsx (bytes=std::vector of length 18655, capacity 32768 = {...}, password=u\"VelvetSweatshop\") at /xlnt/source/detail/cryptography/xlsx_crypto_consumer.cpp:320
#3 0x000000000048a2d9 in xlnt::detail::decrypt_xlsx (data=std::vector of length 18655, capacity 32768 = {...}, password=) at /xlnt/source/detail/cryptography/xlsx_crypto_consumer.cpp:339
#4 0x000000000048a7f6 in xlnt::detail::xlsx_consumer::read (this=0x7fffffffd8f0, source=..., password=) at /xlnt/source/detail/cryptography/xlsx_crypto_consumer.cpp:345
#5 0x000000000040ddd6 in xlnt::workbook::load (this=0x7fffffffdbc8, stream=...) at /xlnt/source/workbook/workbook.cpp:901
#6 0x00000000004142af in xlnt::workbook::load (this=0x7fffffffdbc8, data=std::vector of length 18655, capacity 18655 = {...}) at /xlnt/source/workbook/workbook.cpp:919
#7 0x00000000004073bd in LLVMFuzzerTestOneInput (data=<optimized out>, data@entry=0x6ec0a0 \"\\320\\317\\021\\340\\241\\261\", <incomplete sequence \\341>, size=<optimized out>, size@entry=18655) at /home/avgor46/test_threads_casr/xlnt/load_sydr.cc:13
#8 0x00000000004074cb in main (argc=<optimized out>, argv=<optimized out>) at /home/avgor46/test_threads_casr/xlnt/load_sydr.cc:39
103 changes: 103 additions & 0 deletions libcasr/fuzz/init_corpus/go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
runtime stack:
runtime.throw({0x565860?, 0x400000?})
runtime/panic.go:1047 +0x5f fp=0x7fffffffdb40 sp=0x7fffffffdb10 pc=0x49745f
runtime.sysMapOS(0xc000400000, 0x1b82b8000000?)
runtime/mem_linux.go:187 +0x11b fp=0x7fffffffdb88 sp=0x7fffffffdb40 pc=0x47a93b
runtime.sysMap(0xff9e40?, 0x7ffff7a1b000?, 0x48dc00?)
runtime/mem.go:142 +0x35 fp=0x7fffffffdbb8 sp=0x7fffffffdb88 pc=0x47a315
runtime.(*mheap).grow(0xff9e40, 0xdc15be77?)
runtime/mheap.go:1459 +0x23d fp=0x7fffffffdc28 sp=0x7fffffffdbb8 pc=0x48acbd
runtime.(*mheap).allocSpan(0xff9e40, 0xdc15be77, 0x0, 0x1)
runtime/mheap.go:1191 +0x1be fp=0x7fffffffdcc0 sp=0x7fffffffdc28 pc=0x48a3fe
runtime.(*mheap).alloc.func1()
runtime/mheap.go:910 +0x65 fp=0x7fffffffdd08 sp=0x7fffffffdcc0 pc=0x489e85
runtime.systemstack()
runtime/asm_amd64.s:492 +0x46 fp=0x7fffffffdd10 sp=0x7fffffffdd08 pc=0x4c0ae6

goroutine 17 [running, locked to thread]:
runtime.systemstack_switch()
runtime/asm_amd64.s:459 fp=0xc00005ca98 sp=0xc00005ca90 pc=0x4c0a80
runtime.(*mheap).alloc(0x4c7485?, 0x641d60?, 0x0?)
runtime/mheap.go:904 +0x65 fp=0xc00005cae0 sp=0xc00005ca98 pc=0x489dc5
runtime.(*mcache).allocLarge(0x5bfa08?, 0x1b82b7cec246, 0x1)
runtime/mcache.go:233 +0x85 fp=0xc00005cb30 sp=0xc00005cae0 pc=0x4792a5
runtime.mallocgc(0x1b82b7cec246, 0x5a54e0, 0x1)
runtime/malloc.go:1029 +0x57e fp=0xc00005cba8 sp=0xc00005cb30 pc=0x470ebe
runtime.makeslice(0xc00010c1b0?, 0xc00001c0a0?, 0x8?)
runtime/slice.go:103 +0x52 fp=0xc00005cbd0 sp=0xc00005cba8 pc=0x4ac4d2
golang.org/x/image/webp.readAlpha({0x5bfa68, 0xc0000140b0}, 0x1c0a0?, 0xc0?, 0x1?)
/image/webp/decode.go:157 +0x409 fp=0xc00005cc68 sp=0xc00005cbd0 pc=0x521509
golang.org/x/image/webp.decode({0x5bf9e8?, 0xc00010c1b0?}, 0x0)
/image/webp/decode.go:68 +0x64a fp=0xc00005cd80 sp=0xc00005cc68 pc=0x52070a
golang.org/x/image/webp.Decode({0x5bf9e8?, 0xc00010c1b0?})
/image/webp/decode.go:255 +0x45 fp=0xc00005cda8 sp=0xc00005cd80 pc=0x521ca5
golang.org/x/image.FuzzWebp({0x102a550, 0xc7, 0xc7})
/image/fuzz.go:22 +0x1d8 fp=0xc00005cdd0 sp=0xc00005cda8 pc=0x553098
main.LLVMFuzzerTestOneInput(0x0?, 0xc000006601?)
golang.org/x/image/go.fuzz.main/main.go:35 +0x47 fp=0xc00005ce10 sp=0xc00005cdd0 pc=0x5531c7
_cgoexp_b3dc3ff32902_LLVMFuzzerTestOneInput(0x7fffffffdd80)
_cgo_gotypes.go:58 +0x28 fp=0xc00005ce30 sp=0xc00005ce10 pc=0x5532a8
runtime.cgocallbackg1(0x553280, 0xc00005cfe0?, 0x0)
runtime/cgocall.go:316 +0x2c2 fp=0xc00005cf00 sp=0xc00005ce30 pc=0x468942
runtime.cgocallbackg(0x0?, 0x0?, 0x0?)
runtime/cgocall.go:235 +0x109 fp=0xc00005cf90 sp=0xc00005cf00 pc=0x4685c9
runtime.cgocallbackg(0x553280, 0x7fffffffdd80, 0x0)
<autogenerated>:1 +0x31 fp=0xc00005cfb8 sp=0xc00005cf90 pc=0x4c5011
runtime.cgocallback(0x0, 0x0, 0x0)
runtime/asm_amd64.s:994 +0xb3 fp=0xc00005cfe0 sp=0xc00005cfb8 pc=0x4c2ad3
runtime.goexit()
runtime/asm_amd64.s:1594 +0x1 fp=0xc00005cfe8 sp=0xc00005cfe0 pc=0x4c2d21

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
runtime/proc.go:363 +0xd6 fp=0xc00004afb0 sp=0xc00004af90 pc=0x49a076
runtime.goparkunlock(...)
runtime/proc.go:369
runtime.forcegchelper()
runtime/proc.go:302 +0xad fp=0xc00004afe0 sp=0xc00004afb0 pc=0x499f0d
runtime.goexit()
runtime/asm_amd64.s:1594 +0x1 fp=0xc00004afe8 sp=0xc00004afe0 pc=0x4c2d21
created by runtime.init.6
runtime/proc.go:290 +0x25

goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
runtime/proc.go:363 +0xd6 fp=0xc00004b790 sp=0xc00004b770 pc=0x49a076
runtime.goparkunlock(...)
runtime/proc.go:369
runtime.bgsweep(0x0?)
runtime/mgcsweep.go:278 +0x8e fp=0xc00004b7c8 sp=0xc00004b790 pc=0x486e2e
runtime.gcenable.func1()
runtime/mgc.go:178 +0x26 fp=0xc00004b7e0 sp=0xc00004b7c8 pc=0x47bcc6
runtime.goexit()
runtime/asm_amd64.s:1594 +0x1 fp=0xc00004b7e8 sp=0xc00004b7e0 pc=0x4c2d21
created by runtime.gcenable
runtime/mgc.go:178 +0x6b

goroutine 4 [GC scavenge wait]:
runtime.gopark(0xc000074000?, 0x587370?, 0x1?, 0x0?, 0x0?)
runtime/proc.go:363 +0xd6 fp=0xc00004bf70 sp=0xc00004bf50 pc=0x49a076
runtime.goparkunlock(...)
runtime/proc.go:369
runtime.(*scavengerState).park(0xfe1700)
runtime/mgcscavenge.go:389 +0x53 fp=0xc00004bfa0 sp=0xc00004bf70 pc=0x484ed3
runtime.bgscavenge(0x0?)
runtime/mgcscavenge.go:617 +0x45 fp=0xc00004bfc8 sp=0xc00004bfa0 pc=0x4854a5
runtime.gcenable.func2()
runtime/mgc.go:179 +0x26 fp=0xc00004bfe0 sp=0xc00004bfc8 pc=0x47bc66
runtime.goexit()
runtime/asm_amd64.s:1594 +0x1 fp=0xc00004bfe8 sp=0xc00004bfe0 pc=0x4c2d21
created by runtime.gcenable
runtime/mgc.go:179 +0xaa

goroutine 5 [finalizer wait]:
runtime.gopark(0xfe1b00?, 0xc000007860?, 0x0?, 0x0?, 0xc00004a770?)
runtime/proc.go:363 +0xd6 fp=0xc00004a628 sp=0xc00004a608 pc=0x49a076
runtime.goparkunlock(...)
runtime/proc.go:369
runtime.runfinq()
runtime/mfinal.go:180 +0x10f fp=0xc00004a7e0 sp=0xc00004a628 pc=0x47adcf
runtime.goexit()
runtime/asm_amd64.s:1594 +0x1 fp=0xc00004a7e8 sp=0xc00004a7e0 pc=0x4c2d21
created by runtime.createfing
runtime/mfinal.go:157 +0x45
9 changes: 9 additions & 0 deletions libcasr/fuzz/init_corpus/java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
== Java Exception: java.lang.IndexOutOfBoundsException: start 328, end 292, length 441
at java.base/java.lang.AbstractStringBuilder.checkRange(AbstractStringBuilder.java:1802)
at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:680)
at java.base/java.lang.StringBuilder.append(StringBuilder.java:218)
at com.google.json.JsonSanitizer.elide(JsonSanitizer.java:717)
at com.google.json.JsonSanitizer.normalizeNumber(JsonSanitizer.java:864)
at com.google.json.JsonSanitizer.sanitize(JsonSanitizer.java:440)
at com.google.json.JsonSanitizer.sanitize(JsonSanitizer.java:122)
at DenylistFuzzer.fuzzerTestOneInput(DenylistFuzzer.java:27)
19 changes: 19 additions & 0 deletions libcasr/fuzz/init_corpus/python
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Traceback (most recent call last):
File "../../yaml_fuzzer.py", line 40, in TestOneInput
for _ in iterator:
File "/home/hkctkuy/.local/lib/python3.8/site-packages/ruamel/yaml/main.py", line 461, in load_all
yield constructor.get_data()
File "/home/hkctkuy/.local/lib/python3.8/site-packages/ruamel/yaml/constructor.py", line 114, in get_data
return self.construct_document(self.composer.get_node())
File "/home/hkctkuy/.local/lib/python3.8/site-packages/ruamel/yaml/composer.py", line 66, in get_node
return self.compose_document()
File "/home/hkctkuy/.local/lib/python3.8/site-packages/ruamel/yaml/composer.py", line 99, in compose_document
node = self.compose_node(None, None)
File "/home/hkctkuy/.local/lib/python3.8/site-packages/ruamel/yaml/composer.py", line 139, in compose_node
node = self.compose_scalar_node(anchor)
File "/home/hkctkuy/.local/lib/python3.8/site-packages/ruamel/yaml/composer.py", line 152, in compose_scalar_node
tag = self.resolver.resolve(ScalarNode, event.value, event.implicit)
File "/home/hkctkuy/.local/lib/python3.8/site-packages/ruamel/yaml/resolver.py", line 367, in resolve
resolvers = self.versioned_resolver.get("", [])
File "/home/hkctkuy/.local/lib/python3.8/site-packages/ruamel/yaml/resolver.py", line 361, in versioned_resolver
return self._version_implicit_resolver[version]

0 comments on commit c229bed

Please sign in to comment.