33use libfuzzer_sys:: fuzz_target;
44use std:: str;
55
6- use sql_docs:: fuzz_entry;
6+ use sql_docs:: SqlDoc ;
7+ use std:: { fs, path:: PathBuf } ;
78
89fuzz_target ! ( |data: & [ u8 ] | {
9- if let Ok ( s) = str :: from_utf8( data) {
10- fuzz_entry( s) ;
10+ const MAX_FILES : usize = 16 ;
11+ const MAX_FILE_BYTES : usize = 8 * 1024 ;
12+
13+ if data. is_empty( ) {
14+ return ;
15+ }
16+
17+ let tmp = match tempfile:: tempdir( ) {
18+ Ok ( t) => t,
19+ Err ( _) => return ,
20+ } ;
21+ let root = tmp. path( ) ;
22+
23+ let mut i = 0usize ;
24+ let file_count = ( data[ i] as usize % MAX_FILES ) . max( 1 ) ;
25+ i += 1 ;
26+
27+ for file_idx in 0 ..file_count {
28+ if i >= data. len( ) {
29+ break ;
30+ }
31+
32+ let name_len = ( data[ i] as usize % 24 ) . max( 1 ) ;
33+ i += 1 ;
34+ if i + name_len > data. len( ) {
35+ break ;
36+ }
37+
38+ let name_bytes = & data[ i..i + name_len] ;
39+ i += name_len;
40+
41+ let mut name = String :: with_capacity( name_len) ;
42+ for & b in name_bytes {
43+ name. push( match b {
44+ b'a' ..=b'z' | b'A' ..=b'Z' | b'0' ..=b'9' => b as char ,
45+ _ => '_' ,
46+ } ) ;
47+ }
48+
49+ let ext = if ( file_idx + data[ 0 ] as usize ) % 3 == 0 { "sql" } else { "txt" } ;
50+ let path = root. join( format!( "{name}_{file_idx}.{ext}" ) ) ;
51+
52+ if i + 2 > data. len( ) {
53+ break ;
54+ }
55+ let raw_len = u16 :: from_le_bytes( [ data[ i] , data[ i + 1 ] ] ) as usize ;
56+ i += 2 ;
57+
58+ let content_len = raw_len % MAX_FILE_BYTES ;
59+ if i + content_len > data. len( ) {
60+ break ;
61+ }
62+
63+ let content = & data[ i..i + content_len] ;
64+ i += content_len;
65+
66+ let text = String :: from_utf8_lossy( content) ;
67+ let _ = fs:: write( & path, text. as_bytes( ) ) ;
68+ }
69+ let res = SqlDoc :: from_dir( root) . build( ) ;
70+ if let Err ( e) = res {
71+ let _ = e. to_string( ) ;
72+ let _ = std:: error:: Error :: source( & e) ;
1173 }
12- } ) ;
74+ } ) ;
0 commit comments