Skip to content

Commit

Permalink
Avoid stack overflow when initializing HashBuffers. (#164)
Browse files Browse the repository at this point in the history
Before this commit, `Box::default()` that creates default `HashBuffers`
would in debug mode create the default `HashBuffers` struct on the stack
and then as a separate step copy it into the heap (i.e. into the `Box`).
This would require 164098 bytes of stack space and would trigger stack
overflow in some scenarios (e.g. when running Chromium tests built in
debug-mode on an iOS device - see https://crbug.com/394824910).
  • Loading branch information
anforowicz authored Feb 10, 2025
1 parent 2119168 commit 921bc2c
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 9 deletions.
18 changes: 11 additions & 7 deletions miniz_oxide/src/deflate/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
//! to avoid stack copies. Box::new() doesn't at the moment, and using a vec means we would lose
//! static length info.
use alloc::boxed::Box;
use alloc::vec;
use crate::deflate::core::{LZ_DICT_SIZE, MAX_MATCH_LEN};

/// Size of the buffer of lz77 encoded data.
Expand All @@ -23,24 +25,26 @@ pub fn update_hash(current_hash: u16, byte: u8) -> u16 {
}

pub struct HashBuffers {
pub dict: [u8; LZ_DICT_FULL_SIZE],
pub next: [u16; LZ_DICT_SIZE],
pub hash: [u16; LZ_DICT_SIZE],
pub dict: Box<[u8; LZ_DICT_FULL_SIZE]>,
pub next: Box<[u16; LZ_DICT_SIZE]>,
pub hash: Box<[u16; LZ_DICT_SIZE]>,
}

impl HashBuffers {
#[inline]
pub fn reset(&mut self) {
*self = HashBuffers::default();
self.dict.fill(0);
self.next.fill(0);
self.hash.fill(0);
}
}

impl Default for HashBuffers {
fn default() -> HashBuffers {
HashBuffers {
dict: [0; LZ_DICT_FULL_SIZE],
next: [0; LZ_DICT_SIZE],
hash: [0; LZ_DICT_SIZE],
dict: vec![0; LZ_DICT_FULL_SIZE].into_boxed_slice().try_into().unwrap(),
next: vec![0; LZ_DICT_SIZE].into_boxed_slice().try_into().unwrap(),
hash: vec![0; LZ_DICT_SIZE].into_boxed_slice().try_into().unwrap(),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions miniz_oxide/src/deflate/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,7 @@ pub(crate) struct DictOxide {
pub max_probes: [u32; 2],
/// Buffer of input data.
/// Padded with 1 byte to simplify matching code in `compress_fast`.
pub b: Box<HashBuffers>,
pub b: HashBuffers,

pub code_buf_dict_pos: usize,
pub lookahead_size: usize,
Expand All @@ -1153,7 +1153,7 @@ impl DictOxide {
fn new(flags: u32) -> Self {
DictOxide {
max_probes: probes_from_flags(flags),
b: Box::default(),
b: HashBuffers::default(),
code_buf_dict_pos: 0,
lookahead_size: 0,
lookahead_pos: 0,
Expand Down

0 comments on commit 921bc2c

Please sign in to comment.