Skip to content

Commit

Permalink
Remove last unsafe usage in core crate
Browse files Browse the repository at this point in the history
  • Loading branch information
oyvindln committed Jul 22, 2019
1 parent 0a5a4b9 commit 7bcf211
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 58 deletions.
41 changes: 14 additions & 27 deletions miniz_oxide/src/deflate/core.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Streaming compression functionality.
use std::{cmp, mem, ptr};
use std::{cmp, mem};
use std::convert::TryInto;
use std::io::{self, Cursor, Seek, SeekFrom, Write};

use super::CompressionLevel;
Expand Down Expand Up @@ -532,7 +533,8 @@ impl BitBuffer {
let pos = output.inner.position() as usize;
{ // isolation to please borrow checker
let inner = &mut (*output.inner.get_mut())[pos..pos+8];
inner.copy_from_slice(&u64_to_le_bytes(self.bit_buffer));
let bytes = u64::to_le_bytes(self.bit_buffer);
inner.copy_from_slice(&bytes);
}
output.inner.seek(
SeekFrom::Current(i64::from(self.bits_in >> 3)),
Expand All @@ -543,13 +545,6 @@ impl BitBuffer {
}
}

#[inline]
/// Copy of u64::to_le_bytes() that is only available starting at Rust 1.32,
/// while we want to support older Rust versions
fn u64_to_le_bytes(num: u64) -> [u8; 8] {
unsafe { mem::transmute(num.to_le()) }
}

/// A struct containing data about huffman codes and symbol frequencies.
///
/// NOTE: Only the literal/lengths have enough symbols to actually use
Expand Down Expand Up @@ -1029,23 +1024,17 @@ impl DictOxide {
// Somehow this assertion makes things faster.
assert!(end < LZ_DICT_FULL_SIZE);

let bytes = &self.b.dict[pos..end].as_ptr();
// Unsafe
//
// We just checked the bounds.
unsafe { ptr::read_unaligned(*bytes as *const u32)}
let bytes: [u8; 4] = self.b.dict[pos..end].try_into().unwrap();
u32::from_le_bytes(bytes)
}

/// Do an unaligned read of the data at `pos` in the dictionary and treat it as if it was of
/// type T.
#[inline]
fn read_unaligned_u64(&self, pos: u32) -> u64 {
let pos = pos as usize;
let bytes = &self.b.dict[pos..pos+8];
// Unsafe
//
// We just checked the bounds.
unsafe {ptr::read_unaligned(bytes.as_ptr() as *const u64)}
let bytes: [u8; 8] = self.b.dict[pos..pos+8].try_into().unwrap();
u64::from_le_bytes(bytes)
}


Expand Down Expand Up @@ -1137,8 +1126,8 @@ impl DictOxide {
let mut q = probe_pos + 2;
// The first two bytes matched, so check the full length of the match.
for _ in 0..32 {
let p_data: u64 = u64::from_le(self.read_unaligned_u64(p));
let q_data: u64 = u64::from_le(self.read_unaligned_u64(q));
let p_data: u64 = self.read_unaligned_u64(p);
let q_data: u64 = self.read_unaligned_u64(q);
// Compare of 8 bytes at a time by using unaligned loads of 64-bit integers.
let xor_data = p_data ^ q_data;
if xor_data == 0 {
Expand Down Expand Up @@ -1774,7 +1763,7 @@ fn compress_fast(d: &mut CompressorOxide, callback: &mut CallbackOxide) -> bool
while lookahead_size >= 4 {
let mut cur_match_len = 1;

let first_trigram = u32::from_le(d.dict.read_unaligned_u32(cur_pos)) & 0xFF_FFFF;
let first_trigram = d.dict.read_unaligned_u32(cur_pos) & 0xFF_FFFF;

let hash = (first_trigram ^ (first_trigram >> (24 - (LZ_HASH_BITS - 8)))) &
LEVEL1_HASH_SIZE_MASK;
Expand All @@ -1786,18 +1775,16 @@ fn compress_fast(d: &mut CompressorOxide, callback: &mut CallbackOxide) -> bool
if u32::from(cur_match_dist) <= d.dict.size {
probe_pos &= LZ_DICT_SIZE_MASK;

let trigram = u32::from_le(d.dict.read_unaligned_u32(probe_pos)) & 0xFF_FFFF;
let trigram = d.dict.read_unaligned_u32(probe_pos) & 0xFF_FFFF;

if first_trigram == trigram {
// Trigram was tested, so we can start with "+ 3" displacement.
let mut p = cur_pos + 3;
let mut q = probe_pos + 3;
cur_match_len = 'find_match: loop {
for _ in 0..32 {
let p_data: u64 =
u64::from_le(d.dict.read_unaligned_u64(p));
let q_data: u64 =
u64::from_le(d.dict.read_unaligned_u64(q));
let p_data: u64 = d.dict.read_unaligned_u64(p);
let q_data: u64 = d.dict.read_unaligned_u64(q);
let xor_data = p_data ^ q_data;
if xor_data == 0 {
p += 8;
Expand Down
38 changes: 8 additions & 30 deletions miniz_oxide/src/inflate/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
use super::*;
use crate::shared::{HUFFMAN_LENGTH_ORDER, update_adler32};

use std::{cmp, ptr, slice};
use std::{cmp, slice};
use std::convert::TryInto;

use self::output_buffer::OutputBuffer;

Expand Down Expand Up @@ -178,19 +179,6 @@ impl DecompressorOxide {
self.state = core::State::Start;
}

/// Create a new decompressor with only the state field initialized.
///
/// This is how it's created in miniz. Unsafe due to uninitialized values.
/// Usage is not recommended.
#[inline]
#[deprecated(since = "0.2.2",
note="Will be removed as the safety of using this is hard to verify.")]
pub unsafe fn with_init_state_only() -> DecompressorOxide {
let mut decomp: DecompressorOxide = mem::uninitialized();
decomp.state = core::State::Start;
decomp
}

/// Returns the adler32 checksum of the currently decompressed data.
#[inline]
pub fn adler32(&self) -> Option<u32> {
Expand Down Expand Up @@ -352,17 +340,11 @@ fn memset<T: Copy>(slice: &mut [T], val: T) {
#[inline]
fn read_u16_le(iter: &mut slice::Iter<u8>) -> u16 {
let ret = {
let two_bytes = &iter.as_ref()[0..2];
// # Unsafe
//
// The slice was just bounds checked to be 2 bytes long.
//
// Skip clippy warning as using a cast with this function is ok.
#[allow(clippy::cast_ptr_alignment)]
unsafe { ptr::read_unaligned(two_bytes.as_ptr() as *const u16) }
let two_bytes = iter.as_ref()[..2].try_into().unwrap();
u16::from_le_bytes(two_bytes)
};
iter.nth(1);
u16::from_le(ret)
ret
}

/// Read an le u32 value from the slice iterator.
Expand All @@ -373,15 +355,11 @@ fn read_u16_le(iter: &mut slice::Iter<u8>) -> u16 {
#[cfg(target_pointer_width = "64")]
fn read_u32_le(iter: &mut slice::Iter<u8>) -> u32 {
let ret = {
let four_bytes = &iter.as_ref()[..4];
// # Unsafe
//
// The slice was just bounds checked to be 4 bytes long.
#[allow(clippy::cast_ptr_alignment)]
unsafe { ptr::read_unaligned(four_bytes.as_ptr() as *const u32) }
let four_bytes: [u8; 4] = iter.as_ref()[..4].try_into().unwrap();
u32::from_le_bytes(four_bytes)
};
iter.nth(3);
u32::from_le(ret)
ret
}

/// Ensure that there is data in the bit buffer.
Expand Down
2 changes: 1 addition & 1 deletion miniz_oxide/src/inflate/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! This module contains functionality for decompression.
use std::{mem, usize};
use std::usize;
use std::io::Cursor;

pub mod core;
Expand Down

0 comments on commit 7bcf211

Please sign in to comment.