@@ -2867,3 +2867,162 @@ fn inflate_copy_after_half_input() {
28672867 out[ ..total] . to_vec( )
28682868 } ) ;
28692869}
2870+
2871+ #[ test]
2872+ fn inflate_validate_toggles_checksum_update ( ) {
2873+ let input = include_bytes ! ( "test-data/compression-corpus/The fastest WASM zlib.md.gzip-9.gz" ) ;
2874+
2875+ // Check that `inflateValidate` toggles checksum updating.
2876+ //
2877+ // - decompress normally, the checksum should update
2878+ // - toggle, the checksum should not update
2879+ // - toggle again, the checksum should update
2880+ assert_eq_rs_ng ! ( {
2881+ let mut stream = MaybeUninit :: <z_stream>:: zeroed( ) ;
2882+ let ret = inflateInit2_(
2883+ stream. as_mut_ptr( ) ,
2884+ 16 + 15 , // gzip + max window
2885+ zlibVersion( ) ,
2886+ core:: mem:: size_of:: <z_stream>( ) as c_int,
2887+ ) ;
2888+ assert_eq!( ret, Z_OK ) ;
2889+
2890+ let stream = stream. assume_init_mut( ) ;
2891+
2892+ let mut out1 = vec![ 0u8 ; 16 * 1024 ] ;
2893+ let mut out2 = vec![ 0u8 ; 16 * 1024 ] ;
2894+ let mut out3 = vec![ 0u8 ; 16 * 1024 ] ;
2895+
2896+ let check1 = {
2897+ let ret = inflateValidate( stream, 1 ) ;
2898+ assert_eq!( ret, Z_OK ) ;
2899+
2900+ stream. next_in = input. as_ptr( ) as * mut _;
2901+ stream. avail_in = input. len( ) as _;
2902+ stream. next_out = out1. as_mut_ptr( ) ;
2903+ stream. avail_out = out1. len( ) as _;
2904+
2905+ let ret = loop {
2906+ let ret = inflate( stream, InflateFlush :: NoFlush as _) ;
2907+
2908+ assert!(
2909+ matches!( ret, Z_OK | Z_BUF_ERROR | Z_STREAM_END ) ,
2910+ "unexpected inflate return (run 1): {}" ,
2911+ ret
2912+ ) ;
2913+
2914+ if matches!( ret, Z_STREAM_END ) {
2915+ break ret;
2916+ }
2917+
2918+ if stream. avail_in == 0 {
2919+ break ret;
2920+ }
2921+
2922+ if stream. avail_out == 0 {
2923+ unreachable!( "run 1: not enough output space" ) ;
2924+ }
2925+ } ;
2926+
2927+ assert_eq!( ret, Z_STREAM_END ) ;
2928+ out1. truncate( stream. total_out as usize ) ;
2929+ stream. adler
2930+ } ;
2931+
2932+ assert_eq!( inflateReset( stream) , Z_OK ) ;
2933+
2934+ let check2 = {
2935+ let ret = inflateValidate( stream, 0 ) ;
2936+ assert_eq!( ret, Z_OK ) ;
2937+
2938+ stream. next_in = input. as_ptr( ) as * mut _;
2939+ stream. avail_in = input. len( ) as _;
2940+ stream. next_out = out2. as_mut_ptr( ) ;
2941+ stream. avail_out = out2. len( ) as _;
2942+
2943+ let ret = loop {
2944+ let ret = inflate( stream, InflateFlush :: NoFlush as _) ;
2945+
2946+ assert!(
2947+ matches!( ret, Z_OK | Z_BUF_ERROR | Z_STREAM_END ) ,
2948+ "unexpected inflate return (run 2): {}" ,
2949+ ret
2950+ ) ;
2951+
2952+ if matches!( ret, Z_STREAM_END ) {
2953+ break ret;
2954+ }
2955+
2956+ if stream. avail_in == 0 {
2957+ break ret;
2958+ }
2959+
2960+ if stream. avail_out == 0 {
2961+ unreachable!( "run 2: not enough output space" ) ;
2962+ }
2963+ } ;
2964+
2965+ assert_eq!( ret, Z_STREAM_END ) ;
2966+ out2. truncate( stream. total_out as usize ) ;
2967+ stream. adler
2968+ } ;
2969+
2970+ // Output must be identical, regardless of validation.
2971+ assert_eq!( out1, out2) ;
2972+
2973+ assert_ne!(
2974+ check1, check2,
2975+ "checksum with validation disabled unexpectedly matches the validated checksum" ,
2976+ ) ;
2977+
2978+ assert_eq!( inflateReset( stream) , Z_OK ) ;
2979+
2980+ let check3 = {
2981+ let ret = inflateValidate( stream, 0 ) ;
2982+ assert_eq!( ret, Z_OK ) ;
2983+ let ret = inflateValidate( stream, 1 ) ;
2984+ assert_eq!( ret, Z_OK ) ;
2985+
2986+ stream. next_in = input. as_ptr( ) as * mut _;
2987+ stream. avail_in = input. len( ) as _;
2988+ stream. next_out = out3. as_mut_ptr( ) ;
2989+ stream. avail_out = out3. len( ) as _;
2990+
2991+ let ret = loop {
2992+ let ret = inflate( stream, InflateFlush :: NoFlush as _) ;
2993+
2994+ assert!(
2995+ matches!( ret, Z_OK | Z_BUF_ERROR | Z_STREAM_END ) ,
2996+ "unexpected inflate return (run 3): {}" ,
2997+ ret
2998+ ) ;
2999+
3000+ if matches!( ret, Z_STREAM_END ) {
3001+ break ret;
3002+ }
3003+
3004+ if stream. avail_in == 0 {
3005+ break ret;
3006+ }
3007+
3008+ if stream. avail_out == 0 {
3009+ unreachable!( "run 3: not enough output space" ) ;
3010+ }
3011+ } ;
3012+
3013+ assert_eq!( ret, Z_STREAM_END ) ;
3014+ out3. truncate( stream. total_out as usize ) ;
3015+ stream. adler
3016+ } ;
3017+
3018+ assert_eq!( out1, out3) ;
3019+
3020+ // With validation back on, checksum should again match the first run
3021+ assert_eq!(
3022+ check1, check3,
3023+ "checksum with validation re-enabled does not match validated run"
3024+ ) ;
3025+
3026+ assert_eq!( inflateEnd( stream) , Z_OK ) ;
3027+ } ) ;
3028+ }
0 commit comments