Skip to content

Commit

Permalink
Fix stack overflow from copying large yyjson buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
Dr-Emann authored and ijl committed Aug 7, 2023
1 parent 374fac3 commit caae033
Showing 1 changed file with 21 additions and 7 deletions.
28 changes: 21 additions & 7 deletions src/typeref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use crate::ffi::orjson_fragmenttype_new;
use ahash::RandomState;
use once_cell::race::OnceBox;
use pyo3_ffi::*;
use std::cell::UnsafeCell;
use std::mem::MaybeUninit;
use std::os::raw::c_char;
use std::ptr::{null_mut, NonNull};
use std::sync::Once;
Expand Down Expand Up @@ -88,16 +90,28 @@ pub fn ahash_init() -> Box<ahash::RandomState> {
pub const YYJSON_BUFFER_SIZE: usize = 1024 * 1024 * 8;

#[cfg(feature = "yyjson")]
pub static mut YYJSON_ALLOC: OnceBox<[u8; YYJSON_BUFFER_SIZE]> = OnceBox::new();
#[repr(align(64))]
pub struct YYJSONBuffer(UnsafeCell<MaybeUninit<[u8; YYJSON_BUFFER_SIZE]>>);

#[cfg(feature = "yyjson")]
pub fn yyjson_init() -> Box<[u8; YYJSON_BUFFER_SIZE]> {
impl YYJSONBuffer {
pub(crate) fn as_ptr(&self) -> *mut u8 {
self.0.get().cast::<u8>()
}
}

#[cfg(feature = "yyjson")]
pub static mut YYJSON_ALLOC: OnceBox<YYJSONBuffer> = OnceBox::new();

#[cfg(feature = "yyjson")]
pub fn yyjson_init() -> Box<YYJSONBuffer> {
// Using unsafe to ensure allocation happens on the heap without going through the stack
// so we don't stack overflow in debug mode. Once rust-lang/rust#63291 is stable (Box::new_uninit)
// we can use that instead.
let layout = std::alloc::Layout::new::<YYJSONBuffer>();
unsafe {
let buffer = std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked(
YYJSON_BUFFER_SIZE,
64,
)) as *mut [u8; YYJSON_BUFFER_SIZE];
Box::new(*buffer)
let buffer = std::alloc::alloc(layout);
Box::from_raw(buffer.cast::<YYJSONBuffer>())
}
}

Expand Down

0 comments on commit caae033

Please sign in to comment.