11#![ no_main]
22
33use libfuzzer_sys:: fuzz_target;
4- use cachekit_core:: byte_storage:: { ByteStorage , StorageEnvelope } ;
4+ use cachekit_core:: byte_storage:: { ByteStorage , ByteStorageError , StorageEnvelope } ;
55use arbitrary:: Arbitrary ;
66
77#[ derive( Arbitrary , Debug ) ]
@@ -10,8 +10,8 @@ struct CompressionBombTestCase {
1010 compressed_size : u16 , // 0-65535 bytes
1111 /// Original size claim (potentially massive for bomb attacks)
1212 original_size : u32 ,
13- /// Checksum
14- checksum : [ u8 ; 32 ] ,
13+ /// Checksum (xxHash3-64 = 8 bytes)
14+ checksum : [ u8 ; 8 ] ,
1515 /// Format string length
1616 format_len : u8 ,
1717 /// Actual compressed data pattern (for LZ4 valid/invalid inputs)
@@ -57,37 +57,44 @@ fuzz_target!(|test_case: CompressionBombTestCase| {
5757 ) ;
5858 }
5959 Err ( err) => {
60- // Expected for malicious inputs - verify error is descriptive
60+ // Expected for malicious inputs - verify error type
6161 if test_case. original_size as usize > storage. max_uncompressed_size( ) {
6262 assert!(
63- err. contains( "Security violation" ) || err. contains( "too large" ) ,
64- "Expected size limit error, got: {}" ,
63+ matches!(
64+ err,
65+ ByteStorageError :: InputTooLarge
66+ | ByteStorageError :: DecompressionBomb
67+ | ByteStorageError :: DecompressionFailed
68+ ) ,
69+ "Expected size limit error, got: {:?}" ,
6570 err
6671 ) ;
6772 }
6873 }
6974 }
7075
71- // Property 3: Compression ratio limits enforced (500x max expansion)
76+ // Property 3: Compression ratio limits enforced (1000x max expansion)
7277 if !compressed_data. is_empty( ) && test_case. original_size > 0 {
73- let claimed_ratio = test_case. original_size as f64 / compressed_data. len( ) as f64 ;
78+ let claimed_ratio = test_case. original_size as u64 / compressed_data. len( ) as u64 ;
7479
7580 if claimed_ratio > storage. max_compression_ratio( ) {
7681 // Must reject suspicious ratios (or size limits caught it first)
7782 assert!(
7883 extract_result. is_err( ) ,
79- "Decompression bomb bypassed ratio limit: {:.1}x expansion (1KB -> {}MB)" ,
80- claimed_ratio,
81- test_case. original_size / ( 1024 * 1024 )
84+ "Decompression bomb bypassed ratio limit: {}x expansion" ,
85+ claimed_ratio
8286 ) ;
8387
8488 if let Err ( err) = & extract_result {
8589 // Security checks may fail in different order (size limit or ratio limit)
8690 assert!(
87- err. contains( "Suspicious compression ratio" )
88- || err. contains( "decompression bomb" )
89- || err. contains( "too large" ) , // Size limit caught it first
90- "Expected security violation error, got: {}" ,
91+ matches!(
92+ err,
93+ ByteStorageError :: DecompressionBomb
94+ | ByteStorageError :: InputTooLarge
95+ | ByteStorageError :: DecompressionFailed
96+ ) ,
97+ "Expected security violation error, got: {:?}" ,
9198 err
9299 ) ;
93100 }
@@ -110,10 +117,10 @@ fuzz_target!(|test_case: CompressionBombTestCase| {
110117
111118 // Ratio must be within limits (for non-empty compressed data)
112119 if !compressed_data. is_empty( ) {
113- let actual_ratio = decompressed. len( ) as f64 / compressed_data. len( ) as f64 ;
120+ let actual_ratio = decompressed. len( ) as u64 / compressed_data. len( ) as u64 ;
114121 assert!(
115122 actual_ratio <= storage. max_compression_ratio( ) ,
116- "retrieve() bypassed ratio limit: {:.1 }x" ,
123+ "retrieve() bypassed ratio limit: {}x" ,
117124 actual_ratio
118125 ) ;
119126 }
@@ -130,7 +137,7 @@ fuzz_target!(|test_case: CompressionBombTestCase| {
130137 // Defense-in-depth: Size limits prevent 1KB -> 10GB attacks
131138
132139 // SUCCESS: All compression bomb attack vectors blocked
133- // - Extreme ratios rejected (500x limit)
140+ // - Extreme ratios rejected (1000x limit)
134141 // - Oversized outputs rejected (512MB limit)
135142 // - Malformed LZ4 data handled gracefully
136143 // - No panics, crashes, or memory exhaustion
0 commit comments