Skip to content

Commit

Permalink
fix stack overflow bug when allocate memory using Box::new() by intro…
Browse files Browse the repository at this point in the history
…ducing a Buffer type
  • Loading branch information
thanhminhmr committed May 21, 2023
1 parent 4deeb95 commit 66101c5
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 36 deletions.
44 changes: 44 additions & 0 deletions src/basic/buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* srx: The fast Symbol Ranking based compressor.
* Copyright (C) 2023 Mai Thanh Minh (a.k.a. thanhminhmr)
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/

use std::ops::{Deref, DerefMut};

// -----------------------------------------------

#[derive(Clone)]
pub struct Buffer<T: Copy, const SIZE: usize>(Box<[T]>);

impl<T: Copy, const SIZE: usize> Buffer<T, SIZE> {
pub fn new(value: T) -> Self {
Self(vec![value; SIZE].into_boxed_slice())
}
}

impl<T: Copy, const SIZE: usize> Deref for Buffer<T, SIZE> {
type Target = [T];

fn deref(&self) -> &Self::Target {
self.0.deref()
}
}

impl<T: Copy + Send + 'static, const SIZE: usize> DerefMut for Buffer<T, SIZE> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.deref_mut()
}
}
2 changes: 2 additions & 0 deletions src/basic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
* this program. If not, see <https://www.gnu.org/licenses/>.
*/

mod buffer;
mod error;
mod io;
mod pipe;

pub use self::buffer::Buffer;
pub use self::error::{AnyError, AnyResult};
pub use self::io::{Closable, Consumer, FromProducer, Producer, Reader, ToConsumer, Writer};
pub use self::pipe::{pipe, PipedReader, PipedWriter};
27 changes: 1 addition & 26 deletions src/basic/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,13 @@
* this program. If not, see <https://www.gnu.org/licenses/>.
*/

use crate::basic::buffer::Buffer;
use crate::basic::error::{AnyError, AnyResult};
use crate::basic::io::{Closable, Consumer, FromProducer, Producer, Reader, ToConsumer, Writer};
use std::ops::{Deref, DerefMut};
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};

// -----------------------------------------------

#[derive(Clone)]
struct Buffer<T: Copy + Send + 'static, const SIZE: usize>(Box<[T; SIZE]>);

impl<T: Copy + Send + 'static, const SIZE: usize> Buffer<T, SIZE> {
fn new(value: T) -> Self {
Self(Box::new([value; SIZE]))
}
}

impl<T: Copy + Send + 'static, const SIZE: usize> Deref for Buffer<T, SIZE> {
type Target = [T; SIZE];

fn deref(&self) -> &Self::Target {
self.0.deref()
}
}

impl<T: Copy + Send + 'static, const SIZE: usize> DerefMut for Buffer<T, SIZE> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.deref_mut()
}
}

// -----------------------------------------------

type WriterToReader<T, const SIZE: usize> = (Buffer<T, SIZE>, usize);
type ReaderToWriter<T, const SIZE: usize> = Buffer<T, SIZE>;

Expand Down
17 changes: 9 additions & 8 deletions src/primary_context/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* this program. If not, see <https://www.gnu.org/licenses/>.
*/

use crate::basic::Buffer;
use crate::primary_context::matched::ByteMatched;
use crate::primary_context::history::ByteHistory;

Expand All @@ -24,7 +25,7 @@ use crate::primary_context::history::ByteHistory;
pub struct PrimaryContext<const SIZE: usize> {
previous_byte: u8,
hash_value: usize,
contexts: Box<[ByteHistory; SIZE]>,
context: Buffer<ByteHistory, SIZE>,
}

impl<const SIZE: usize> PrimaryContext<SIZE> {
Expand All @@ -35,24 +36,24 @@ impl<const SIZE: usize> PrimaryContext<SIZE> {
Self {
previous_byte: 0,
hash_value: 0,
contexts: Box::new([ByteHistory::new(); SIZE]),
context: Buffer::new(ByteHistory::new()),
}
}

pub fn first_byte(&self) -> u8 {
self.contexts[self.hash_value].first_byte()
self.context[self.hash_value].first_byte()
}

pub fn second_byte(&self) -> u8 {
self.contexts[self.hash_value].second_byte()
self.context[self.hash_value].second_byte()
}

pub fn third_byte(&self) -> u8 {
self.contexts[self.hash_value].third_byte()
self.context[self.hash_value].third_byte()
}

pub fn match_count(&self) -> usize {
self.contexts[self.hash_value].match_count()
self.context[self.hash_value].match_count()
}

pub fn previous_byte(&self) -> u8 {
Expand All @@ -70,13 +71,13 @@ impl<const SIZE: usize> PrimaryContext<SIZE> {
}

pub fn matching(&mut self, next_byte: u8) -> ByteMatched {
let matching_byte: ByteMatched = self.contexts[self.hash_value].matching(next_byte);
let matching_byte: ByteMatched = self.context[self.hash_value].matching(next_byte);
self.update(next_byte);
return matching_byte;
}

pub fn matched(&mut self, next_byte: u8, matched: ByteMatched) {
self.contexts[self.hash_value].matched(next_byte, matched);
self.context[self.hash_value].matched(next_byte, matched);
self.update(next_byte);
}
}
5 changes: 3 additions & 2 deletions src/secondary_context/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@
* this program. If not, see <https://www.gnu.org/licenses/>.
*/

use crate::basic::Buffer;
use crate::secondary_context::bit::Bit;
use crate::secondary_context::prediction::BitPrediction;

pub struct SecondaryContext<const SIZE: usize> {
context: Box<[BitPrediction; SIZE]>,
context: Buffer<BitPrediction, SIZE>,
}

impl<const SIZE: usize> SecondaryContext<SIZE> {
pub fn new() -> Self {
Self {
context: Box::new([BitPrediction::new(); SIZE]),
context: Buffer::new(BitPrediction::new()),
}
}

Expand Down

0 comments on commit 66101c5

Please sign in to comment.