@@ -2540,3 +2540,166 @@ fn test_deflate_get_dict() {
25402540 dictionary
25412541 } ) ;
25422542}
2543+
2544+ #[ derive( Debug , Clone ) ]
2545+ struct GzHeaderData {
2546+ text : i32 ,
2547+ time : core:: ffi:: c_ulong ,
2548+ os : i32 ,
2549+ extra : Vec < u8 > ,
2550+ name : CString ,
2551+ comment : CString ,
2552+ hcrc : i32 ,
2553+ }
2554+
2555+ impl GzHeaderData {
2556+ fn as_gz_header ( & mut self ) -> libz_rs_sys:: gz_header {
2557+ libz_rs_sys:: gz_header {
2558+ text : self . text ,
2559+ time : self . time ,
2560+ xflags : 0 ,
2561+ os : self . os ,
2562+ extra : self . extra . as_mut_ptr ( ) ,
2563+ extra_len : self . extra . len ( ) . try_into ( ) . unwrap ( ) ,
2564+ extra_max : 0 , // doesn't matter for writing.
2565+ name : self . name . as_ptr ( ) as * mut u8 , // hack: UB if written to, but we shouldn't write during deflate.
2566+ name_max : 0 , // doesn't matter for writing.
2567+ comment : self . comment . as_ptr ( ) as * mut u8 , // hack: UB if written to, but we shouldn't write during deflate.
2568+ comm_max : 0 , // doesn't matter for writing.
2569+ hcrc : self . hcrc ,
2570+ done : 0 , // doesn't matter for writing.
2571+ }
2572+ }
2573+ }
2574+
2575+ #[ derive( Debug ) ]
2576+ struct Input {
2577+ source : String ,
2578+ config : DeflateConfig ,
2579+ flush : DeflateFlush ,
2580+ header : GzHeaderData ,
2581+ }
2582+
2583+ #[ test]
2584+ fn test_gzip_deflate_config ( ) {
2585+ let input = Input {
2586+ source : "\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 ~\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 _\0 \0 \0 \0 %\0 \0 \0 \0 \0 \0 \0 \0 \0 \u{13} \0 \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} i\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ b\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \0 \0 \0 \0 \0 \0 \\ \\ \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{1a} \u{1b} \u{1b} &\u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \0 \u{3} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \\ \\ \\ \0 \0 \0 \0 \0 \0 \0 _\0 \0 \0 \0 %\0 \0 \0 \0 \0 \0 \0 \0 \0 \u{13} \0 \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} i\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ b\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \0 \0 \0 \0 \0 \0 \\ \\ \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn\u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{1a} \u{1b} \u{1b} &\u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \0 \u{3} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \\ \\ \\ \\ \\ \\ L\\ \\ L\\ \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \0 \u{3} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \u{7f} \\ \\ \\ \\ \\ \\ L\\ \\ L\\ *" . to_owned ( ) ,
2587+ config : DeflateConfig {
2588+ level : -1 ,
2589+ method : Method :: Deflated ,
2590+ window_bits : 31 ,
2591+ mem_level : 1 ,
2592+ strategy : Strategy :: Fixed ,
2593+ } ,
2594+ flush : DeflateFlush :: Block ,
2595+ header : GzHeaderData {
2596+ text : -120653576 ,
2597+ time : 17940362863843014904u64 as _ , // may truncate, that's fine.
2598+ os : -1 ,
2599+ extra : vec ! [
2600+ 0 ,
2601+ ] ,
2602+ name : CString :: default ( ) ,
2603+ comment : CString :: from ( c"\xff \xff \xff \xff \xff \xff \xff \xff \xff \xff " ) ,
2604+ hcrc : 1548508252 ,
2605+ } ,
2606+ } ;
2607+
2608+ assert_eq_rs_ng ! ( {
2609+ let Input {
2610+ ref source,
2611+ config,
2612+ flush,
2613+ ref header,
2614+ } = input;
2615+
2616+ let mut header = header. clone( ) ;
2617+
2618+ // Initialize stream.
2619+ let mut stream = core:: mem:: MaybeUninit :: zeroed( ) ;
2620+ let err = unsafe {
2621+ deflateInit2_(
2622+ stream. as_mut_ptr( ) ,
2623+ config. level,
2624+ config. method as i32 ,
2625+ config. window_bits,
2626+ config. mem_level,
2627+ config. strategy as i32 ,
2628+ zlibVersion( ) ,
2629+ size_of:: <z_stream>( ) as c_int,
2630+ )
2631+ } ;
2632+
2633+ assert_eq!( err, ReturnCode :: Ok as i32 ) ;
2634+
2635+ let streamp = unsafe { stream. assume_init_mut( ) } ;
2636+
2637+ // Create header.
2638+ let mut header = unsafe {
2639+ #[ allow( clippy:: useless_transmute) ]
2640+ core:: mem:: transmute:: <libz_rs_sys:: gz_header, gz_header>( header. as_gz_header( ) )
2641+ } ;
2642+ let err = unsafe { deflateSetHeader( streamp, & mut header as gz_headerp) } ;
2643+ if err != ReturnCode :: Ok as i32 {
2644+ // Deallocate, so that we don't trigger ASAN leak detector.
2645+ let err = unsafe { deflateEnd( streamp) } ;
2646+ assert_eq!( err, ReturnCode :: Ok as i32 ) ;
2647+ return ;
2648+ }
2649+
2650+ let bound = unsafe { deflateBound( streamp, source. len( ) as _) } ;
2651+ let buf_size = match flush {
2652+ DeflateFlush :: NoFlush | DeflateFlush :: Finish => bound,
2653+ // Other flush options might require more than `bound` bytes, so add a safety margin. We
2654+ // _could_ catch Z_BUF_ERROR to allocate more memory, but that's not interesting right now.
2655+ // (In fact, it's more interesting if NoFlush/Finish triggers UB write if we're
2656+ // miscalculating)
2657+ DeflateFlush :: PartialFlush
2658+ | DeflateFlush :: SyncFlush
2659+ | DeflateFlush :: FullFlush
2660+ | DeflateFlush :: Block => bound * 2 ,
2661+ } ;
2662+
2663+ // We deliberately use uninitialized memory as the input buffer here, to simulate how these
2664+ // functions will likely be used from C, and to catch us ever reading uninitialized memory.
2665+ let mut dest: Vec <u8 > = Vec :: with_capacity( buf_size as usize ) ;
2666+
2667+ let max = c_uint:: MAX as usize ;
2668+
2669+ let mut left = dest. capacity( ) ;
2670+ let mut source_len = source. len( ) ;
2671+
2672+ streamp. next_in = source. as_ptr( ) . cast_mut( ) . cast( ) ;
2673+ streamp. next_out = dest. as_mut_ptr( ) . cast( ) ;
2674+
2675+ loop {
2676+ if streamp. avail_out == 0 {
2677+ streamp. avail_out = Ord :: min( left, max) as _;
2678+ left -= streamp. avail_out as usize ;
2679+ }
2680+
2681+ if streamp. avail_in == 0 {
2682+ streamp. avail_in = Ord :: min( source_len, max) as _;
2683+ source_len -= streamp. avail_in as usize ;
2684+ }
2685+
2686+ let flush = if source_len > 0 {
2687+ flush
2688+ } else {
2689+ DeflateFlush :: Finish
2690+ } ;
2691+
2692+ let err = unsafe { deflate( streamp, flush as i32 ) } ;
2693+ if ReturnCode :: from( err) != ReturnCode :: Ok {
2694+ break ;
2695+ }
2696+ }
2697+
2698+ unsafe { dest. set_len( streamp. total_out as usize ) }
2699+
2700+ let err = unsafe { deflateEnd( streamp) } ;
2701+ assert_eq!( ReturnCode :: from( err) , ReturnCode :: Ok ) ;
2702+
2703+ Some ( dest)
2704+ } ) ;
2705+ }
0 commit comments