libsoliton/soliton_capi/fuzz/fuzz_targets/fuzz_capi_stream_decrypt.rs
Kamal Tufekcic d73755a275
initial commit
Signed-off-by: Kamal Tufekcic <kamal@lo.sh>
2026-04-23 15:51:07 +03:00

53 lines
1.5 KiB
Rust

#![no_main]
use libfuzzer_sys::fuzz_target;
use std::ptr;
fuzz_target!(|data: &[u8]| {
// Exercise the CAPI streaming decryption path with adversarial input.
// Tests header validation, AEAD rejection, decompression bounds,
// and output buffer handling through the FFI boundary.
if data.len() < 26 {
return;
}
let key = [0x42u8; 32];
let header = &data[..26];
let rest = &data[26..];
let mut dec: *mut soliton_capi::SolitonStreamDecryptor = ptr::null_mut();
let rc = unsafe {
soliton_capi::soliton_stream_decrypt_init(
key.as_ptr(), 32,
header.as_ptr(), 26,
ptr::null(), 0,
&mut dec,
)
};
if rc != 0 || dec.is_null() {
return;
}
// Feed remaining bytes as chunks in 2048-byte slices.
// 1 MiB chunk size + 256-byte zstd overhead margin — matches STREAM_CHUNK_SIZE.
let out_cap = 1_048_576 + 256;
let mut out_buf = vec![0u8; out_cap];
for chunk_data in rest.chunks(2048) {
let mut out_written: usize = 0;
let mut is_final: bool = false;
let rc = unsafe {
soliton_capi::soliton_stream_decrypt_chunk(
dec,
chunk_data.as_ptr(), chunk_data.len(),
out_buf.as_mut_ptr(), out_cap,
&mut out_written,
&mut is_final,
)
};
if rc != 0 || is_final {
break;
}
}
unsafe { soliton_capi::soliton_stream_decrypt_free(&mut dec); }
});