@@ -51,7 +51,7 @@ struct GzState {
5151 source : Source ,
5252 want : usize , // requested buffer size, default is GZBUFSIZE
5353 input : * mut u8 , // input buffer (double-sized when writing)
54- in_size : usize , // size of * input
54+ in_size : usize , // usable size of input buffer (See [`gz_init`] for explanation.)
5555 output : * mut u8 , // output buffer (double-sized when reading)
5656 out_size : usize , // size of *output
5757 direct : bool , // true in pass-through mode, false if processing gzip data
@@ -112,6 +112,22 @@ impl GzState {
112112 Ok ( ( exclusive, cloexec) )
113113 }
114114
115+ // Get the number of bytes allocated for the `self.input` buffer.
116+ fn in_capacity ( & self ) -> usize {
117+ match self . mode {
118+ GzMode :: GZ_WRITE => self . want * 2 ,
119+ _ => self . want ,
120+ }
121+ }
122+
123+ // Get the number of bytes allocated for the `self.output` buffer.
124+ fn out_capacity ( & self ) -> usize {
125+ match self . mode {
126+ GzMode :: GZ_READ => self . want * 2 ,
127+ _ => self . want ,
128+ }
129+ }
130+
115131 /// Compute the number of bytes of input buffered in `self`.
116132 ///
117133 /// # Safety
@@ -509,14 +525,14 @@ unsafe fn free_buffers(state: &mut GzState) {
509525 if !state. input . is_null ( ) {
510526 // Safety: state.input is always allocated using ALLOCATOR, and
511527 // its allocation size is stored in state.in_size.
512- unsafe { ALLOCATOR . deallocate ( state. input , state. in_size ) } ;
528+ unsafe { ALLOCATOR . deallocate ( state. input , state. in_capacity ( ) ) } ;
513529 state. input = ptr:: null_mut ( ) ;
514530 }
515531 state. in_size = 0 ;
516532 if !state. output . is_null ( ) {
517- // Safety: state.input is always allocated using ALLOCATOR, and
518- // its allocation size is stored in state.in_size .
519- unsafe { ALLOCATOR . deallocate ( state. output , state. out_size ) } ;
533+ // Safety: state.output is always allocated using ALLOCATOR, and
534+ // its allocation size is stored in state.out_size .
535+ unsafe { ALLOCATOR . deallocate ( state. output , state. out_capacity ( ) ) } ;
520536 state. output = ptr:: null_mut ( ) ;
521537 }
522538 state. out_size = 0 ;
@@ -1185,17 +1201,19 @@ fn gz_skip(state: &mut GzState, mut len: i64) -> Result<(), ()> {
11851201unsafe fn gz_look ( state : & mut GzState ) -> Result < ( ) , ( ) > {
11861202 // Allocate buffers if needed.
11871203 if state. input . is_null ( ) {
1188- state. in_size = state. want ;
1189- let Some ( input) = ALLOCATOR . allocate_slice_raw :: < u8 > ( state. in_size ) else {
1204+ let capacity = state. in_capacity ( ) ;
1205+ state. in_size = capacity;
1206+ let Some ( input) = ALLOCATOR . allocate_slice_raw :: < u8 > ( capacity) else {
11901207 // Safety: The caller confirmed the validity of state.
11911208 unsafe { gz_error ( state, Some ( ( Z_MEM_ERROR , "out of memory" ) ) ) } ;
11921209 return Err ( ( ) ) ;
11931210 } ;
11941211 state. input = input. as_ptr ( ) ;
11951212
11961213 if state. output . is_null ( ) {
1197- state. out_size = state. want * 2 ;
1198- let Some ( output) = ALLOCATOR . allocate_slice_raw :: < u8 > ( state. out_size ) else {
1214+ let capacity = state. out_capacity ( ) ;
1215+ state. out_size = capacity;
1216+ let Some ( output) = ALLOCATOR . allocate_slice_raw :: < u8 > ( capacity) else {
11991217 // Safety: The caller confirmed the validity of state, and free_buffers checks
12001218 // for null input and output pointers internally.
12011219 unsafe { free_buffers ( state) } ;
@@ -1705,9 +1723,14 @@ fn gz_zero(state: &mut GzState, mut len: usize) -> Result<(), ()> {
17051723// - `Ok` on success.
17061724// - `Err` on error.
17071725fn gz_init ( state : & mut GzState ) -> Result < ( ) , ( ) > {
1708- // Allocate input buffer (double size for gzprintf).
1709- state. in_size = state. want * 2 ;
1710- let Some ( input) = ALLOCATOR . allocate_slice_raw :: < u8 > ( state. in_size ) else {
1726+ // Allocate input buffer.
1727+ // The buffer is twice as big as state.want, but we set in_size to half the
1728+ // buffer size (i.e. state.in_size == state.want). The reason for this is to
1729+ // ensure that we always have state.want bytes available for exclusive use
1730+ // by gzprintf.
1731+ let capacity = state. in_capacity ( ) ;
1732+ state. in_size = capacity / 2 ;
1733+ let Some ( input) = ALLOCATOR . allocate_slice_raw :: < u8 > ( capacity) else {
17111734 // Safety: The caller confirmed the validity of state.
17121735 unsafe { gz_error ( state, Some ( ( Z_MEM_ERROR , "out of memory" ) ) ) } ;
17131736 return Err ( ( ) ) ;
@@ -1718,8 +1741,9 @@ fn gz_init(state: &mut GzState) -> Result<(), ()> {
17181741 // Only need output buffer and deflate state if compressing.
17191742 if !state. direct {
17201743 // Allocate output buffer.
1721- state. out_size = state. want ;
1722- let Some ( output) = ALLOCATOR . allocate_slice_raw :: < u8 > ( state. out_size ) else {
1744+ let capacity = state. out_capacity ( ) ;
1745+ state. out_size = capacity;
1746+ let Some ( output) = ALLOCATOR . allocate_slice_raw :: < u8 > ( capacity) else {
17231747 unsafe { free_buffers ( state) } ;
17241748 // Safety: The caller confirmed the validity of state.
17251749 unsafe { gz_error ( state, Some ( ( Z_MEM_ERROR , "out of memory" ) ) ) } ;
0 commit comments