Skip to content

Commit c378248

Browse files
authored
Use the error message from z_stream.msg for [De]CompressError (#270)
* Use the error message from z_stream.msg for [De]CompressError * Don't make the size of Error types bigger if msg is always going to be None * Clean up cfg()s for zlib vs any_zlib * Test error messages on invalid data
1 parent 7546110 commit c378248

File tree

4 files changed

+167
-122
lines changed

4 files changed

+167
-122
lines changed

src/ffi/c.rs

Lines changed: 72 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,23 @@ pub use libc::{c_int, c_uint, c_void, size_t};
1212
use super::*;
1313
use crate::mem::{self, FlushDecompress, Status};
1414

15+
// miniz doesn't provide any error messages, so only enable the field when we use a real zlib
16+
#[derive(Default)]
17+
pub struct ErrorMessage(#[cfg(feature = "any_zlib")] Option<&'static str>);
18+
19+
impl ErrorMessage {
20+
pub fn get(&self) -> Option<&str> {
21+
#[cfg(feature = "any_zlib")]
22+
{
23+
self.0
24+
}
25+
#[cfg(not(feature = "any_zlib"))]
26+
{
27+
None
28+
}
29+
}
30+
}
31+
1532
pub struct StreamWrapper {
1633
pub inner: Box<mz_stream>,
1734
}
@@ -138,6 +155,25 @@ pub struct Stream<D: Direction> {
138155
pub _marker: marker::PhantomData<D>,
139156
}
140157

158+
impl<D: Direction> Stream<D> {
159+
pub fn msg(&self) -> ErrorMessage {
160+
#[cfg(feature = "any_zlib")]
161+
{
162+
let msg = self.stream_wrapper.msg;
163+
ErrorMessage(if msg.is_null() {
164+
None
165+
} else {
166+
let s = unsafe { std::ffi::CStr::from_ptr(msg) };
167+
std::str::from_utf8(s.to_bytes()).ok()
168+
})
169+
}
170+
#[cfg(not(feature = "any_zlib"))]
171+
{
172+
ErrorMessage()
173+
}
174+
}
175+
}
176+
141177
impl<D: Direction> Drop for Stream<D> {
142178
fn drop(&mut self) {
143179
unsafe {
@@ -193,6 +229,7 @@ impl InflateBackend for Inflate {
193229
flush: FlushDecompress,
194230
) -> Result<Status, DecompressError> {
195231
let raw = &mut *self.inner.stream_wrapper;
232+
raw.msg = ptr::null_mut();
196233
raw.next_in = input.as_ptr() as *mut u8;
197234
raw.avail_in = cmp::min(input.len(), c_uint::max_value() as usize) as c_uint;
198235
raw.next_out = output.as_mut_ptr();
@@ -206,7 +243,7 @@ impl InflateBackend for Inflate {
206243
self.inner.total_out += (raw.next_out as usize - output.as_ptr() as usize) as u64;
207244

208245
match rc {
209-
MZ_DATA_ERROR | MZ_STREAM_ERROR => mem::decompress_failed(),
246+
MZ_DATA_ERROR | MZ_STREAM_ERROR => mem::decompress_failed(self.inner.msg()),
210247
MZ_OK => Ok(Status::Ok),
211248
MZ_BUF_ERROR => Ok(Status::BufError),
212249
MZ_STREAM_END => Ok(Status::StreamEnd),
@@ -286,6 +323,7 @@ impl DeflateBackend for Deflate {
286323
flush: FlushCompress,
287324
) -> Result<Status, CompressError> {
288325
let raw = &mut *self.inner.stream_wrapper;
326+
raw.msg = ptr::null_mut();
289327
raw.next_in = input.as_ptr() as *mut _;
290328
raw.avail_in = cmp::min(input.len(), c_uint::max_value() as usize) as c_uint;
291329
raw.next_out = output.as_mut_ptr();
@@ -302,7 +340,7 @@ impl DeflateBackend for Deflate {
302340
MZ_OK => Ok(Status::Ok),
303341
MZ_BUF_ERROR => Ok(Status::BufError),
304342
MZ_STREAM_END => Ok(Status::StreamEnd),
305-
MZ_STREAM_ERROR => Err(CompressError(())),
343+
MZ_STREAM_ERROR => mem::compress_failed(self.inner.msg()),
306344
c => panic!("unknown return code: {}", c),
307345
}
308346
}
@@ -336,103 +374,41 @@ mod c_backend {
336374
pub type AllocSize = libc::size_t;
337375
}
338376

339-
/// Zlib specific
340-
#[cfg(any(
341-
feature = "zlib-ng-compat",
342-
all(feature = "zlib", not(feature = "cloudflare_zlib"))
343-
))]
344-
#[allow(bad_style)]
345-
mod c_backend {
346-
use libc::{c_char, c_int};
347-
use std::mem;
348-
349-
pub use libz_sys::deflate as mz_deflate;
350-
pub use libz_sys::deflateEnd as mz_deflateEnd;
351-
pub use libz_sys::deflateReset as mz_deflateReset;
352-
pub use libz_sys::inflate as mz_inflate;
353-
pub use libz_sys::inflateEnd as mz_inflateEnd;
354-
pub use libz_sys::z_stream as mz_stream;
355-
pub use libz_sys::*;
356-
357-
pub use libz_sys::Z_BLOCK as MZ_BLOCK;
358-
pub use libz_sys::Z_BUF_ERROR as MZ_BUF_ERROR;
359-
pub use libz_sys::Z_DATA_ERROR as MZ_DATA_ERROR;
360-
pub use libz_sys::Z_DEFAULT_STRATEGY as MZ_DEFAULT_STRATEGY;
361-
pub use libz_sys::Z_DEFLATED as MZ_DEFLATED;
362-
pub use libz_sys::Z_FINISH as MZ_FINISH;
363-
pub use libz_sys::Z_FULL_FLUSH as MZ_FULL_FLUSH;
364-
pub use libz_sys::Z_NEED_DICT as MZ_NEED_DICT;
365-
pub use libz_sys::Z_NO_FLUSH as MZ_NO_FLUSH;
366-
pub use libz_sys::Z_OK as MZ_OK;
367-
pub use libz_sys::Z_PARTIAL_FLUSH as MZ_PARTIAL_FLUSH;
368-
pub use libz_sys::Z_STREAM_END as MZ_STREAM_END;
369-
pub use libz_sys::Z_STREAM_ERROR as MZ_STREAM_ERROR;
370-
pub use libz_sys::Z_SYNC_FLUSH as MZ_SYNC_FLUSH;
371-
pub type AllocSize = libz_sys::uInt;
372-
373-
pub const MZ_DEFAULT_WINDOW_BITS: c_int = 15;
374-
375-
const ZLIB_VERSION: &'static str = "1.2.8\0";
376-
377-
pub unsafe extern "C" fn mz_deflateInit2(
378-
stream: *mut mz_stream,
379-
level: c_int,
380-
method: c_int,
381-
window_bits: c_int,
382-
mem_level: c_int,
383-
strategy: c_int,
384-
) -> c_int {
385-
libz_sys::deflateInit2_(
386-
stream,
387-
level,
388-
method,
389-
window_bits,
390-
mem_level,
391-
strategy,
392-
ZLIB_VERSION.as_ptr() as *const c_char,
393-
mem::size_of::<mz_stream>() as c_int,
394-
)
395-
}
396-
pub unsafe extern "C" fn mz_inflateInit2(stream: *mut mz_stream, window_bits: c_int) -> c_int {
397-
libz_sys::inflateInit2_(
398-
stream,
399-
window_bits,
400-
ZLIB_VERSION.as_ptr() as *const c_char,
401-
mem::size_of::<mz_stream>() as c_int,
402-
)
403-
}
404-
}
405-
406-
/// Cloudflare optimized Zlib specific
407-
#[cfg(all(feature = "cloudflare_zlib", not(feature = "zlib-ng-compat")))]
377+
/// Zlib specific - make zlib mimic miniz' API
378+
#[cfg(feature = "any_zlib")]
408379
#[allow(bad_style)]
409380
mod c_backend {
410381
use libc::{c_char, c_int};
411382
use std::mem;
412383

413-
pub use cloudflare_zlib_sys::deflate as mz_deflate;
414-
pub use cloudflare_zlib_sys::deflateEnd as mz_deflateEnd;
415-
pub use cloudflare_zlib_sys::deflateReset as mz_deflateReset;
416-
pub use cloudflare_zlib_sys::inflate as mz_inflate;
417-
pub use cloudflare_zlib_sys::inflateEnd as mz_inflateEnd;
418-
pub use cloudflare_zlib_sys::z_stream as mz_stream;
419-
pub use cloudflare_zlib_sys::*;
420-
421-
pub use cloudflare_zlib_sys::Z_BLOCK as MZ_BLOCK;
422-
pub use cloudflare_zlib_sys::Z_BUF_ERROR as MZ_BUF_ERROR;
423-
pub use cloudflare_zlib_sys::Z_DATA_ERROR as MZ_DATA_ERROR;
424-
pub use cloudflare_zlib_sys::Z_DEFAULT_STRATEGY as MZ_DEFAULT_STRATEGY;
425-
pub use cloudflare_zlib_sys::Z_DEFLATED as MZ_DEFLATED;
426-
pub use cloudflare_zlib_sys::Z_FINISH as MZ_FINISH;
427-
pub use cloudflare_zlib_sys::Z_FULL_FLUSH as MZ_FULL_FLUSH;
428-
pub use cloudflare_zlib_sys::Z_NEED_DICT as MZ_NEED_DICT;
429-
pub use cloudflare_zlib_sys::Z_NO_FLUSH as MZ_NO_FLUSH;
430-
pub use cloudflare_zlib_sys::Z_OK as MZ_OK;
431-
pub use cloudflare_zlib_sys::Z_PARTIAL_FLUSH as MZ_PARTIAL_FLUSH;
432-
pub use cloudflare_zlib_sys::Z_STREAM_END as MZ_STREAM_END;
433-
pub use cloudflare_zlib_sys::Z_STREAM_ERROR as MZ_STREAM_ERROR;
434-
pub use cloudflare_zlib_sys::Z_SYNC_FLUSH as MZ_SYNC_FLUSH;
435-
pub type AllocSize = cloudflare_zlib_sys::uInt;
384+
#[cfg(feature = "cloudflare_zlib")]
385+
use cloudflare_zlib_sys as libz;
386+
#[cfg(not(feature = "cloudflare_zlib"))]
387+
use libz_sys as libz;
388+
389+
pub use libz::deflate as mz_deflate;
390+
pub use libz::deflateEnd as mz_deflateEnd;
391+
pub use libz::deflateReset as mz_deflateReset;
392+
pub use libz::inflate as mz_inflate;
393+
pub use libz::inflateEnd as mz_inflateEnd;
394+
pub use libz::z_stream as mz_stream;
395+
pub use libz::*;
396+
397+
pub use libz::Z_BLOCK as MZ_BLOCK;
398+
pub use libz::Z_BUF_ERROR as MZ_BUF_ERROR;
399+
pub use libz::Z_DATA_ERROR as MZ_DATA_ERROR;
400+
pub use libz::Z_DEFAULT_STRATEGY as MZ_DEFAULT_STRATEGY;
401+
pub use libz::Z_DEFLATED as MZ_DEFLATED;
402+
pub use libz::Z_FINISH as MZ_FINISH;
403+
pub use libz::Z_FULL_FLUSH as MZ_FULL_FLUSH;
404+
pub use libz::Z_NEED_DICT as MZ_NEED_DICT;
405+
pub use libz::Z_NO_FLUSH as MZ_NO_FLUSH;
406+
pub use libz::Z_OK as MZ_OK;
407+
pub use libz::Z_PARTIAL_FLUSH as MZ_PARTIAL_FLUSH;
408+
pub use libz::Z_STREAM_END as MZ_STREAM_END;
409+
pub use libz::Z_STREAM_ERROR as MZ_STREAM_ERROR;
410+
pub use libz::Z_SYNC_FLUSH as MZ_SYNC_FLUSH;
411+
pub type AllocSize = libz::uInt;
436412

437413
pub const MZ_DEFAULT_WINDOW_BITS: c_int = 15;
438414

@@ -446,7 +422,7 @@ mod c_backend {
446422
mem_level: c_int,
447423
strategy: c_int,
448424
) -> c_int {
449-
cloudflare_zlib_sys::deflateInit2_(
425+
libz::deflateInit2_(
450426
stream,
451427
level,
452428
method,
@@ -458,7 +434,7 @@ mod c_backend {
458434
)
459435
}
460436
pub unsafe extern "C" fn mz_inflateInit2(stream: *mut mz_stream, window_bits: c_int) -> c_int {
461-
cloudflare_zlib_sys::inflateInit2_(
437+
libz::inflateInit2_(
462438
stream,
463439
window_bits,
464440
ZLIB_VERSION.as_ptr() as *const c_char,

src/ffi/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,9 @@ cfg_if::cfg_if! {
4444
pub use self::rust::*;
4545
}
4646
}
47+
48+
impl std::fmt::Debug for ErrorMessage {
49+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
50+
self.get().fmt(f)
51+
}
52+
}

src/ffi/rust.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ pub const MZ_FINISH: isize = MZFlush::Finish as isize;
1616
use super::*;
1717
use crate::mem;
1818

19+
// miniz_oxide doesn't provide any error messages (yet?)
20+
#[derive(Default)]
21+
pub struct ErrorMessage;
22+
23+
impl ErrorMessage {
24+
pub fn get(&self) -> Option<&str> {
25+
None
26+
}
27+
}
28+
1929
fn format_from_bool(zlib_header: bool) -> DataFormat {
2030
if zlib_header {
2131
DataFormat::Zlib
@@ -73,7 +83,7 @@ impl InflateBackend for Inflate {
7383
},
7484
Err(status) => match status {
7585
MZError::Buf => Ok(Status::BufError),
76-
_ => mem::decompress_failed(),
86+
_ => mem::decompress_failed(ErrorMessage),
7787
},
7888
}
7989
}
@@ -144,11 +154,11 @@ impl DeflateBackend for Deflate {
144154
Ok(status) => match status {
145155
MZStatus::Ok => Ok(Status::Ok),
146156
MZStatus::StreamEnd => Ok(Status::StreamEnd),
147-
MZStatus::NeedDict => Err(CompressError(())),
157+
MZStatus::NeedDict => mem::compress_failed(ErrorMessage),
148158
},
149159
Err(status) => match status {
150160
MZError::Buf => Ok(Status::BufError),
151-
_ => Err(CompressError(())),
161+
_ => mem::compress_failed(ErrorMessage),
152162
},
153163
}
154164
}

0 commit comments

Comments
 (0)