@@ -42,10 +42,14 @@ pub(crate) trait DeflateBackend: Backend {
42
42
all( target_arch = "wasm32" , not( target_os = "emscripten" ) )
43
43
) ) ) ]
44
44
pub ( crate ) mod imp {
45
- use std:: { cmp, marker} ;
45
+ use std:: alloc:: { self , Layout } ;
46
+ use std:: cmp;
47
+ use std:: convert:: TryFrom ;
48
+ use std:: marker;
46
49
use std:: ops:: { Deref , DerefMut } ;
50
+ use std:: ptr;
47
51
48
- pub use libc:: { c_int, c_uint} ;
52
+ pub use libc:: { c_int, c_uint, c_void , size_t } ;
49
53
50
54
use super :: * ;
51
55
use mem:: { self , FlushDecompress , Status } ;
@@ -62,17 +66,84 @@ pub(crate) mod imp {
62
66
63
67
impl Default for StreamWrapper {
64
68
fn default ( ) -> StreamWrapper {
65
- // Temporary workaround due to bug in libz-sys.
66
- // Error non-boxed function pointers in data structure),
67
- // these are not actually used.
68
- #[ allow( unknown_lints) ]
69
- #[ allow( invalid_value) ]
70
69
StreamWrapper {
71
- inner : Box :: new ( unsafe { std:: mem:: zeroed ( ) } ) ,
70
+ inner : Box :: new ( mz_stream {
71
+ next_in : ptr:: null_mut ( ) ,
72
+ avail_in : 0 ,
73
+ total_in : 0 ,
74
+ next_out : ptr:: null_mut ( ) ,
75
+ avail_out : 0 ,
76
+ total_out : 0 ,
77
+ msg : ptr:: null_mut ( ) ,
78
+ adler : 0 ,
79
+ data_type : 0 ,
80
+ reserved : 0 ,
81
+ opaque : ptr:: null_mut ( ) ,
82
+ state : ptr:: null_mut ( ) ,
83
+ #[ cfg( feature = "zlib" ) ]
84
+ zalloc,
85
+ #[ cfg( feature = "zlib" ) ]
86
+ zfree,
87
+ #[ cfg( not( feature = "zlib" ) ) ]
88
+ zalloc : Some ( zalloc) ,
89
+ #[ cfg( not( feature = "zlib" ) ) ]
90
+ zfree : Some ( zfree) ,
91
+ } ) ,
72
92
}
73
93
}
74
94
}
75
95
96
+ const ALIGN : usize = std:: mem:: align_of :: < usize > ( ) ;
97
+
98
+ fn align_up ( size : usize , align : usize ) -> usize {
99
+ ( size + align - 1 ) & !( align - 1 )
100
+ }
101
+
102
+ extern "C" fn zalloc ( _ptr : * mut c_void , items : AllocSize , item_size : AllocSize ) -> * mut c_void {
103
+ // We need to multiply `items` and `item_size` to get the actual desired
104
+ // allocation size. Since `zfree` doesn't receive a size argument we
105
+ // also need to allocate space for a `usize` as a header so we can store
106
+ // how large the allocation is to deallocate later.
107
+ let size = match items
108
+ . checked_mul ( item_size)
109
+ . and_then ( |i| usize:: try_from ( i) . ok ( ) )
110
+ . map ( |size| align_up ( size, ALIGN ) )
111
+ . and_then ( |i| i. checked_add ( std:: mem:: size_of :: < usize > ( ) ) )
112
+ {
113
+ Some ( i) => i,
114
+ None => return ptr:: null_mut ( ) ,
115
+ } ;
116
+
117
+ // Make sure the `size` isn't too big to fail `Layout`'s restrictions
118
+ let layout = match Layout :: from_size_align ( size, ALIGN ) {
119
+ Ok ( layout) => layout,
120
+ Err ( _) => return ptr:: null_mut ( ) ,
121
+ } ;
122
+
123
+ unsafe {
124
+ // Allocate the data, and if successful store the size we allocated
125
+ // at the beginning and then return an offset pointer.
126
+ let ptr = alloc:: alloc ( layout) as * mut usize ;
127
+ if ptr. is_null ( ) {
128
+ return ptr as * mut c_void ;
129
+ }
130
+ * ptr = size;
131
+ ptr. add ( 1 ) as * mut c_void
132
+ }
133
+ }
134
+
135
+ extern "C" fn zfree ( _ptr : * mut c_void , address : * mut c_void ) {
136
+ unsafe {
137
+ // Move our address being free'd back one pointer, read the size we
138
+ // stored in `zalloc`, and then free it using the standard Rust
139
+ // allocator.
140
+ let ptr = ( address as * mut usize ) . offset ( -1 ) ;
141
+ let size = * ptr;
142
+ let layout = Layout :: from_size_align_unchecked ( size, ALIGN ) ;
143
+ alloc:: dealloc ( ptr as * mut u8 , layout)
144
+ }
145
+ }
146
+
76
147
impl Deref for StreamWrapper {
77
148
type Target = mz_stream ;
78
149
@@ -314,6 +385,7 @@ pub(crate) mod imp {
314
385
extern crate miniz_sys;
315
386
316
387
pub use self :: miniz_sys:: * ;
388
+ pub type AllocSize = libc:: size_t ;
317
389
}
318
390
319
391
/// Zlib specific
@@ -346,6 +418,7 @@ pub(crate) mod imp {
346
418
pub use self :: z:: Z_STREAM_END as MZ_STREAM_END ;
347
419
pub use self :: z:: Z_STREAM_ERROR as MZ_STREAM_ERROR ;
348
420
pub use self :: z:: Z_SYNC_FLUSH as MZ_SYNC_FLUSH ;
421
+ pub type AllocSize = self :: z:: uInt ;
349
422
350
423
pub const MZ_DEFAULT_WINDOW_BITS : c_int = 15 ;
351
424
@@ -370,7 +443,10 @@ pub(crate) mod imp {
370
443
mem:: size_of :: < mz_stream > ( ) as c_int ,
371
444
)
372
445
}
373
- pub unsafe extern "C" fn mz_inflateInit2 ( stream : * mut mz_stream , window_bits : c_int ) -> c_int {
446
+ pub unsafe extern "C" fn mz_inflateInit2 (
447
+ stream : * mut mz_stream ,
448
+ window_bits : c_int ,
449
+ ) -> c_int {
374
450
z:: inflateInit2_ (
375
451
stream,
376
452
window_bits,
@@ -384,7 +460,6 @@ pub(crate) mod imp {
384
460
pub ( crate ) use self :: CInflate as Inflate ;
385
461
}
386
462
387
-
388
463
/// Implementation for miniz_oxide rust backend.
389
464
#[ cfg( any(
390
465
all( not( feature = "zlib" ) , feature = "rust_backend" ) ,
0 commit comments