src-tauri/fuzz: nmh_session drives a whole kestrove-nmh connection through Broker::serve (framing, outer JSON, pair_init/pair_confirm/open/msg); frame_read checks read_frame. 8 min each (2.5 M / 2.7 M execs): no findings. Co-Authored-By: Claude Opus 5.5 <[email protected]>
62 lines
1.7 KiB
Rust
62 lines
1.7 KiB
Rust
//! A whole `kestrove-nmh` connection as the app's Broker sees it: length-prefixed frames, outer
|
|
//! JSON, and the pairing / open / msg handlers (src/broker.rs). The input is the byte stream the
|
|
//! browser side sends; replies go to a sink. Each frame must get exactly one well-formed reply.
|
|
#![no_main]
|
|
use std::io::{self, Read, Write};
|
|
use std::sync::{Arc, OnceLock};
|
|
|
|
use kestrove_desktop::broker::{Broker, PairingStore, PairingView, SaveView, Ui};
|
|
use kestrove_desktop::framing::read_json;
|
|
use kv_ffi::VaultCore;
|
|
use libfuzzer_sys::fuzz_target;
|
|
|
|
struct NoUi;
|
|
impl Ui for NoUi {
|
|
fn pairing_requested(&self, _: &PairingView) {}
|
|
fn save_requested(&self, _: &SaveView) {}
|
|
}
|
|
|
|
struct Duplex<'a> {
|
|
input: &'a [u8],
|
|
output: Vec<u8>,
|
|
}
|
|
impl Read for Duplex<'_> {
|
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
self.input.read(buf)
|
|
}
|
|
}
|
|
impl Write for Duplex<'_> {
|
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
self.output.write(buf)
|
|
}
|
|
fn flush(&mut self) -> io::Result<()> {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn broker() -> &'static Arc<Broker> {
|
|
static B: OnceLock<Arc<Broker>> = OnceLock::new();
|
|
B.get_or_init(|| {
|
|
Broker::new(
|
|
VaultCore::new_in_memory(),
|
|
Arc::new(NoUi),
|
|
PairingStore::in_memory(),
|
|
)
|
|
})
|
|
}
|
|
|
|
fuzz_target!(|data: &[u8]| {
|
|
let mut io = Duplex {
|
|
input: data,
|
|
output: Vec::new(),
|
|
};
|
|
let _ = broker().serve(&mut io);
|
|
let mut replies = io.output.as_slice();
|
|
while let Some(v) = read_json(&mut replies).expect("app replies are valid frames") {
|
|
assert!(
|
|
v.get("t").and_then(|t| t.as_str()).is_some(),
|
|
"reply without t: {v}"
|
|
);
|
|
}
|
|
});
|