Skip to content

Commit c9f0e57

Browse files
committed
unsafe reworkings
1 parent 0f83221 commit c9f0e57

File tree

7 files changed

+67
-71
lines changed

7 files changed

+67
-71
lines changed

libz-rs-sys/src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ pub unsafe extern "C" fn inflate(strm: *mut z_stream, flush: i32) -> i32 {
9090

9191
pub unsafe extern "C" fn inflateEnd(strm: *mut z_stream) -> i32 {
9292
match InflateStream::from_stream_mut(strm) {
93-
Some(stream) => zlib_rs::inflate::end(stream) as _,
93+
Some(stream) => {
94+
zlib_rs::inflate::end(stream);
95+
ReturnCode::Ok as _
96+
}
9497
None => ReturnCode::StreamError as _,
9598
}
9699
}
@@ -345,7 +348,10 @@ pub extern "C" fn compressBound(sourceLen: c_ulong) -> c_ulong {
345348

346349
pub unsafe extern "C" fn deflateEnd(strm: *mut z_stream) -> i32 {
347350
match DeflateStream::from_stream_mut(strm) {
348-
Some(stream) => zlib_rs::deflate::end(stream) as _,
351+
Some(stream) => match zlib_rs::deflate::end(stream) {
352+
Ok(_) => ReturnCode::Ok as _,
353+
Err(_) => ReturnCode::DataError as _,
354+
},
349355
None => ReturnCode::StreamError as _,
350356
}
351357
}

zlib-rs/src/allocate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ unsafe fn zng_free(ptr: *mut c_void) {
6969
unsafe { libc::free(ptr) };
7070
}
7171

72+
#[derive(Clone, Copy)]
7273
#[repr(C)]
7374
pub(crate) struct Allocator<'a> {
7475
pub(crate) zalloc: crate::c_api::alloc_func,

zlib-rs/src/deflate.rs

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ pub struct DeflateStream<'a> {
3535
pub(crate) total_out: crate::c_api::z_size,
3636
pub(crate) msg: *const libc::c_char,
3737
pub(crate) state: &'a mut State<'a>,
38-
pub(crate) zalloc: crate::c_api::alloc_func,
39-
pub(crate) zfree: crate::c_api::free_func,
40-
pub(crate) opaque: crate::c_api::voidpf,
38+
pub(crate) alloc: Allocator<'a>,
4139
pub(crate) data_type: libc::c_int,
4240
pub(crate) adler: crate::c_api::z_checksum,
4341
pub(crate) reserved: crate::c_api::uLong,
@@ -74,6 +72,11 @@ impl<'a> DeflateStream<'a> {
7472

7573
Some(stream)
7674
}
75+
76+
fn as_z_stream_mut(&mut self) -> &mut z_stream {
77+
// safety: a valid &mut DeflateStream is also a valid &mut z_stream
78+
unsafe { &mut *(self as *mut DeflateStream as *mut z_stream) }
79+
}
7780
}
7881

7982
/// number of elements in hash table
@@ -258,11 +261,11 @@ pub fn init(stream: &mut z_stream, config: DeflateConfig) -> ReturnCode {
258261
if let Some(mut sym_buf) = sym_buf {
259262
alloc.deallocate(sym_buf.as_mut_ptr(), sym_buf.capacity())
260263
}
261-
if let Some(mut pending) = pending {
264+
if let Some(pending) = pending {
262265
pending.drop_in(&alloc);
263266
}
264267
if let Some(head) = head {
265-
alloc.deallocate(head.as_mut_ptr(), HASH_SIZE)
268+
alloc.deallocate(head.as_mut_ptr(), 1)
266269
}
267270
if let Some(prev) = prev {
268271
alloc.deallocate(prev.as_mut_ptr(), prev.len())
@@ -434,12 +437,7 @@ pub fn copy<'a>(
434437
core::ptr::copy_nonoverlapping(source, dest.as_mut_ptr(), 1);
435438
}
436439

437-
let alloc = Allocator {
438-
zalloc: source.zalloc,
439-
zfree: source.zfree,
440-
opaque: source.opaque,
441-
_marker: PhantomData,
442-
};
440+
let alloc = &source.alloc;
443441

444442
// allocated here to have the same order as zlib
445443
let Some(state_allocation) = alloc.allocate::<State>() else {
@@ -448,13 +446,13 @@ pub fn copy<'a>(
448446

449447
let source_state = &source.state;
450448

451-
let window = source_state.window.clone_in(&alloc);
449+
let window = source_state.window.clone_in(alloc);
452450

453451
let prev = alloc.allocate_slice::<u16>(source_state.w_size);
454452
let head = alloc.allocate::<[u16; HASH_SIZE]>();
455453

456-
let pending = source_state.pending.clone_in(&alloc);
457-
let sym_buf = source_state.sym_buf.clone_in(&alloc);
454+
let pending = source_state.pending.clone_in(alloc);
455+
let sym_buf = source_state.sym_buf.clone_in(alloc);
458456

459457
// if any allocation failed, clean up allocations that did succeed
460458
let (window, prev, head, pending, sym_buf) = match (window, prev, head, pending, sym_buf) {
@@ -471,8 +469,8 @@ pub fn copy<'a>(
471469
if let Some(mut sym_buf) = sym_buf {
472470
alloc.deallocate(sym_buf.as_mut_ptr(), sym_buf.capacity())
473471
}
474-
if let Some(mut pending) = pending {
475-
pending.drop_in(&alloc);
472+
if let Some(pending) = pending {
473+
pending.drop_in(alloc);
476474
}
477475
if let Some(head) = head {
478476
alloc.deallocate(head.as_mut_ptr(), HASH_SIZE)
@@ -481,7 +479,7 @@ pub fn copy<'a>(
481479
alloc.deallocate(prev.as_mut_ptr(), prev.len())
482480
}
483481
if let Some(mut window) = window {
484-
window.drop_in(&alloc);
482+
window.drop_in(alloc);
485483
}
486484

487485
alloc.deallocate(state_allocation.as_mut_ptr(), 1);
@@ -558,37 +556,37 @@ pub fn copy<'a>(
558556
ReturnCode::Ok
559557
}
560558

561-
pub fn end(stream: &mut DeflateStream) -> ReturnCode {
559+
/// # Returns
560+
///
561+
/// - Err when deflate is not done. A common cause is insufficient output space
562+
/// - Ok otherwise
563+
pub fn end<'a>(stream: &'a mut DeflateStream) -> Result<&'a mut z_stream, &'a mut z_stream> {
562564
let status = stream.state.status;
563565

564-
let sym_buf = stream.state.sym_buf.as_mut_ptr();
565-
let pending = stream.state.pending.as_mut_ptr();
566-
let head = stream.state.head.as_mut_ptr();
567-
let prev = stream.state.prev.as_mut_ptr();
568-
let window = stream.state.window.as_mut_ptr();
569-
let state = stream.state as *mut State;
566+
let alloc = stream.alloc;
570567

571-
let opaque = stream.opaque;
572-
let free = stream.zfree;
568+
// deallocate in reverse order of allocations
569+
unsafe {
570+
// safety: we make sure that these fields are not used (by invalidating the state pointer)
571+
stream.state.sym_buf.drop_in(&alloc);
572+
stream.state.pending.drop_in(&alloc);
573+
alloc.deallocate(stream.state.head, 1);
574+
alloc.deallocate(stream.state.prev.as_mut_ptr(), stream.state.prev.len());
575+
stream.state.window.drop_in(&alloc);
576+
}
573577

574-
// safety: a valid &mut DeflateStream is also a valid &mut z_stream
575-
let stream = unsafe { &mut *(stream as *mut DeflateStream as *mut z_stream) };
578+
let state = stream.state as *mut State;
579+
let stream = stream.as_z_stream_mut();
576580
stream.state = std::ptr::null_mut();
577581

578-
// deallocate in reverse order of allocations
582+
// safety: `state` is not used later
579583
unsafe {
580-
free(opaque, sym_buf.cast());
581-
free(opaque, pending.cast());
582-
free(opaque, head.cast());
583-
free(opaque, prev.cast());
584-
free(opaque, window.cast());
585-
586-
free(opaque, state.cast());
584+
alloc.deallocate(state, 1);
587585
}
588586

589587
match status {
590-
Status::Busy => ReturnCode::DataError,
591-
_ => ReturnCode::Ok,
588+
Status::Busy => Err(stream),
589+
_ => Ok(stream),
592590
}
593591
}
594592

@@ -2561,7 +2559,8 @@ pub fn compress<'a>(
25612559
};
25622560

25632561
if let Some(stream) = unsafe { DeflateStream::from_stream_mut(&mut stream) } {
2564-
end(stream);
2562+
// error gets ignored here
2563+
let _ = end(stream);
25652564
}
25662565

25672566
(output_slice, ReturnCode::Ok)
@@ -3041,7 +3040,7 @@ mod test {
30413040
assert_eq!(deflate(stream, Flush::NoFlush), ReturnCode::Ok);
30423041

30433042
// but end is not
3044-
assert_eq!(end(stream), ReturnCode::DataError);
3043+
assert!(end(stream).is_err());
30453044
}
30463045

30473046
#[test]
@@ -3512,7 +3511,7 @@ mod test {
35123511

35133512
let n = stream.total_out as usize;
35143513

3515-
assert_eq!(end(stream), ReturnCode::Ok);
3514+
assert!(end(stream).is_ok());
35163515

35173516
let output_rs = &mut output[..n];
35183517

@@ -3567,7 +3566,7 @@ mod test {
35673566

35683567
let n = stream.total_out as usize;
35693568

3570-
assert_eq!(end(stream), ReturnCode::Ok);
3569+
assert!(end(stream).is_ok());
35713570

35723571
let output_rs = &mut output[..n];
35733572

zlib-rs/src/deflate/pending.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ pub struct Pending<'a> {
1111
}
1212

1313
impl<'a> Pending<'a> {
14-
pub fn as_mut_ptr(&mut self) -> *mut u8 {
15-
self.buf
16-
}
17-
1814
pub fn reset_keep(&mut self) {
1915
// keep the buffer as it is
2016
self.pending = 0;
@@ -92,7 +88,7 @@ impl<'a> Pending<'a> {
9288
Some(clone)
9389
}
9490

95-
pub(crate) unsafe fn drop_in(&mut self, alloc: &Allocator) {
91+
pub(crate) unsafe fn drop_in(&self, alloc: &Allocator) {
9692
let len = self.end as usize - self.buf as usize;
9793
alloc.deallocate(self.buf, len);
9894
}

zlib-rs/src/deflate/window.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,6 @@ impl<'a> Window<'a> {
6767
unsafe { slice_assume_init_mut(slice) }
6868
}
6969

70-
pub fn as_mut_ptr(&mut self) -> *mut u8 {
71-
self.buf.as_mut_ptr() as *mut u8
72-
}
73-
7470
/// # Safety
7571
///
7672
/// `src` must point to `range.end - range.start` valid (initialized!) bytes

zlib-rs/src/inflate.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ impl<'a> InflateStream<'a> {
115115

116116
Some(stream)
117117
}
118+
119+
fn as_z_stream_mut(&mut self) -> &mut z_stream {
120+
// safety: a valid &mut InflateStream is also a valid &mut z_stream
121+
unsafe { &mut *(self as *mut _ as *mut z_stream) }
122+
}
118123
}
119124

120125
const MAX_BITS: u8 = 15; // maximum number of bits in a code
@@ -212,7 +217,7 @@ pub fn uncompress<'a>(
212217

213218
let avail_out = stream.avail_out;
214219

215-
unsafe { end(stream) };
220+
end(stream);
216221

217222
let ret = match err {
218223
ReturnCode::StreamEnd => ReturnCode::Ok,
@@ -2119,33 +2124,26 @@ pub fn set_dictionary(stream: &mut InflateStream, dictionary: &[u8]) -> ReturnCo
21192124
ReturnCode::Ok
21202125
}
21212126

2122-
/// # Safety
2123-
///
2124-
/// The `strm` must be either NULL or a valid mutable reference to a z_stream value where the state
2125-
/// has been initialized with `inflateInit_` or `inflateInit2_`.
2126-
pub unsafe extern "C" fn end(stream: &mut InflateStream) -> i32 {
2127+
pub fn end<'a>(stream: &'a mut InflateStream) -> &'a mut z_stream {
21272128
let mut state = State::new(&[], ReadBuf::new(&mut []));
21282129
std::mem::swap(&mut state, stream.state);
21292130

21302131
let mut window = Window::empty();
21312132
std::mem::swap(&mut window, &mut state.window);
21322133

2133-
window.drop_in(&stream.alloc);
2134+
let alloc = stream.alloc;
21342135

2135-
let alloc = Allocator {
2136-
zalloc: stream.alloc.zalloc,
2137-
zfree: stream.alloc.zfree,
2138-
opaque: stream.alloc.opaque,
2139-
_marker: PhantomData,
2140-
};
2136+
// safety: window is not used again
2137+
unsafe { window.drop_in(&stream.alloc) };
21412138

2142-
// safety: a valid &mut InflateStream is also a valid &mut z_stream
2143-
let stream = unsafe { &mut *(stream as *mut _ as *mut z_stream) };
2139+
let stream = stream.as_z_stream_mut();
21442140

21452141
let state_ptr = std::mem::replace(&mut stream.state, std::ptr::null_mut());
2146-
alloc.deallocate(state_ptr, 1);
21472142

2148-
ReturnCode::Ok as _
2143+
// safety: state_ptr is not used again
2144+
unsafe { alloc.deallocate(state_ptr as *mut State, 1) };
2145+
2146+
stream
21492147
}
21502148

21512149
pub fn get_header<'a>(

zlib-rs/src/inflate/window.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ impl<'a> Window<'a> {
168168
})
169169
}
170170

171-
pub unsafe fn drop_in(&mut self, alloc: &Allocator) {
171+
pub unsafe fn drop_in(mut self, alloc: &Allocator) {
172172
if !self.buf.is_empty() {
173173
let buf = core::mem::take(&mut self.buf);
174174
alloc.deallocate(buf.as_mut_ptr(), self.buf.len());

0 commit comments

Comments
 (0)