11#![ no_main]
2- use libbz2_rs_sys:: { BZ_FINISH , BZ_OK , BZ_STREAM_END } ;
2+ use libbz2_rs_sys:: { BZ_FINISH , BZ_FINISH_OK , BZ_OK , BZ_STREAM_END } ;
33use libfuzzer_sys:: fuzz_target;
44
55fn compress_c ( data : & [ u8 ] ) -> Vec < u8 > {
6- // first, deflate the data using the standard zlib
7- let length = 8 * 1024 ;
8- let mut deflated = vec ! [ 0u8 ; length as usize ] ;
6+ // First, decompress the data with the stock C bzip2.
7+ let mut output = vec ! [ 0u8 ; 1024 ] ;
98
109 let mut stream = bzip2_sys:: bz_stream {
1110 next_in : data. as_ptr ( ) as * mut _ ,
1211 avail_in : data. len ( ) as _ ,
1312 total_in_lo32 : 0 ,
1413 total_in_hi32 : 0 ,
15- next_out : deflated . as_mut_ptr ( ) as * mut _ ,
16- avail_out : deflated . len ( ) as _ ,
14+ next_out : output . as_mut_ptr ( ) as * mut _ ,
15+ avail_out : output . len ( ) as _ ,
1716 total_out_lo32 : 0 ,
1817 total_out_hi32 : 0 ,
1918 state : std:: ptr:: null_mut ( ) ,
@@ -27,11 +26,32 @@ fn compress_c(data: &[u8]) -> Vec<u8> {
2726 assert_eq ! ( err, BZ_OK ) ;
2827 } ;
2928
30- let error = unsafe { bzip2_sys:: BZ2_bzCompress ( & mut stream, BZ_FINISH ) } ;
29+ let error = loop {
30+ match unsafe { bzip2_sys:: BZ2_bzCompress ( & mut stream, BZ_FINISH ) } {
31+ BZ_FINISH_OK => {
32+ let used = output. len ( ) - stream. avail_out as usize ;
33+ // The output buffer is full.
34+ let add_space: u32 = Ord :: max ( 1024 , output. len ( ) . try_into ( ) . unwrap ( ) ) ;
35+ output. resize ( output. len ( ) + add_space as usize , 0 ) ;
3136
32- assert_eq ! ( error, BZ_STREAM_END ) ;
37+ // If resize() reallocates, it may have moved in memory.
38+ stream. next_out = output. as_mut_ptr ( ) . cast :: < i8 > ( ) . wrapping_add ( used as usize ) ;
39+ stream. avail_out += add_space;
3340
34- deflated. truncate (
41+ continue ;
42+ }
43+ BZ_STREAM_END => {
44+ break BZ_OK ;
45+ }
46+ ret => {
47+ break ret;
48+ }
49+ }
50+ } ;
51+
52+ assert_eq ! ( error, BZ_OK ) ;
53+
54+ output. truncate (
3555 ( ( u64:: from ( stream. total_out_hi32 ) << 32 ) + u64:: from ( stream. total_out_lo32 ) )
3656 . try_into ( )
3757 . unwrap ( ) ,
@@ -42,10 +62,12 @@ fn compress_c(data: &[u8]) -> Vec<u8> {
4262 assert_eq ! ( err, BZ_OK ) ;
4363 }
4464
45- deflated
65+ output
4666}
4767
4868fuzz_target ! ( |input: ( String , usize ) | {
69+ use libbz2_rs_sys:: * ;
70+
4971 let ( data, chunk_size) = input;
5072
5173 if chunk_size == 0 {
@@ -54,10 +76,10 @@ fuzz_target!(|input: (String, usize)| {
5476
5577 let deflated = compress_c( data. as_bytes( ) ) ;
5678
57- let mut stream = libbz2_rs_sys :: bz_stream:: zeroed( ) ;
79+ let mut stream = bz_stream:: zeroed( ) ;
5880
5981 unsafe {
60- let err = libbz2_rs_sys :: BZ2_bzDecompressInit ( & mut stream, 0 , 0 ) ;
82+ let err = BZ2_bzDecompressInit ( & mut stream, 0 , 0 ) ;
6183 assert_eq!( err, BZ_OK ) ;
6284 } ;
6385
@@ -69,13 +91,23 @@ fuzz_target!(|input: (String, usize)| {
6991 stream. next_in = chunk. as_ptr( ) as * mut _;
7092 stream. avail_in = chunk. len( ) as _;
7193
72- let err = unsafe { libbz2_rs_sys :: BZ2_bzDecompress ( & mut stream) } ;
94+ let err = unsafe { BZ2_bzDecompress ( & mut stream) } ;
7395 match err {
7496 BZ_OK => continue ,
97+ BZ_RUN_OK => panic!( "BZ_RUN_OK" ) ,
98+ BZ_FLUSH_OK => panic!( "BZ_FLUSH_OK" ) ,
99+ BZ_FINISH_OK => panic!( "BZ_FINISH_OK" ) ,
75100 BZ_STREAM_END => continue ,
76- _ => {
77- panic!( "{err}" ) ;
78- }
101+ BZ_SEQUENCE_ERROR => panic!( "BZ_SEQUENCE_ERROR" ) ,
102+ BZ_PARAM_ERROR => panic!( "BZ_PARAM_ERROR" ) ,
103+ BZ_MEM_ERROR => panic!( "BZ_MEM_ERROR" ) ,
104+ BZ_DATA_ERROR => panic!( "BZ_DATA_ERROR" ) ,
105+ BZ_DATA_ERROR_MAGIC => panic!( "BZ_DATA_ERROR_MAGIC" ) ,
106+ BZ_IO_ERROR => panic!( "BZ_IO_ERROR" ) ,
107+ BZ_UNEXPECTED_EOF => panic!( "BZ_UNEXPECTED_EOF" ) ,
108+ BZ_OUTBUFF_FULL => panic!( "BZ_OUTBUFF_FULL" ) ,
109+ BZ_CONFIG_ERROR => panic!( "BZ_CONFIG_ERROR" ) ,
110+ _ => panic!( "{err}" ) ,
79111 }
80112 }
81113
@@ -87,7 +119,7 @@ fuzz_target!(|input: (String, usize)| {
87119 let output = String :: from_utf8( output) . unwrap( ) ;
88120
89121 unsafe {
90- let err = libbz2_rs_sys :: BZ2_bzDecompressEnd ( & mut stream) ;
122+ let err = BZ2_bzDecompressEnd ( & mut stream) ;
91123 assert_eq!( err, BZ_OK ) ;
92124 }
93125
0 commit comments