transaction_v2.rs (1452B)
1 #![no_main] 2 3 use iuna::domain::{TransactionV2, fuzz_verify_ml_dsa44}; 4 use libfuzzer_sys::fuzz_target; 5 6 const PUBLIC_KEY_BYTES: usize = 1_312; 7 const SIGNATURE_BYTES: usize = 2_420; 8 const MAX_INPUT_BYTES: usize = 2 * 1024 * 1024; 9 10 fuzz_target!(|data: &[u8]| { 11 if data.len() > MAX_INPUT_BYTES { 12 return; 13 } 14 15 exercise(data); 16 if let Some(hex) = data.strip_prefix(b"hex:") { 17 if let Some(decoded) = decode_hex(hex) { 18 exercise(&decoded); 19 } 20 } 21 }); 22 23 fn exercise(data: &[u8]) { 24 if let Ok((domain, transaction)) = TransactionV2::decode(data) { 25 let _ = transaction.verify_authorizations(&domain); 26 let _ = transaction.encode(&domain); 27 } 28 29 if let Some((public_key, rest)) = data.split_at_checked(PUBLIC_KEY_BYTES) 30 && let Some((signature, payload)) = rest.split_at_checked(SIGNATURE_BYTES) 31 { 32 fuzz_verify_ml_dsa44(public_key, payload, signature); 33 } 34 } 35 36 fn decode_hex(encoded: &[u8]) -> Option<Vec<u8>> { 37 if encoded.len() % 2 != 0 || encoded.len() / 2 > MAX_INPUT_BYTES { 38 return None; 39 } 40 encoded 41 .chunks_exact(2) 42 .map(|pair| Some(decode_nibble(pair[0])? << 4 | decode_nibble(pair[1])?)) 43 .collect() 44 } 45 46 fn decode_nibble(byte: u8) -> Option<u8> { 47 match byte { 48 b'0'..=b'9' => Some(byte - b'0'), 49 b'a'..=b'f' => Some(byte - b'a' + 10), 50 b'A'..=b'F' => Some(byte - b'A' + 10), 51 _ => None, 52 } 53 }