#![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); } });