diff --git a/crates/rope/src/rope.rs b/crates/rope/src/rope.rs index 508e7569c3b5e872aeeacd0ae86e9c9ff1521e7a..958d366866bb0972b0f8f71982a093ca053154db 100644 --- a/crates/rope/src/rope.rs +++ b/crates/rope/src/rope.rs @@ -2216,6 +2216,27 @@ mod tests { } } + #[test] + fn test_rayon_stack_overflow() { + let sz = 2usize.pow(30); + let layout = std::alloc::Layout::from_size_align(sz, 16).unwrap(); + // SAFETY: Size is nonzero. + let massive_alloc = unsafe { std::alloc::alloc(layout) }; + // SAFETY: `sz` is the same as used for the allocation and the pointer is unaliased. + unsafe { massive_alloc.write_bytes(b'A', sz) }; + // SAFETY: `massive_alloc` is initialised by the write above for `sz * sizeof(u8)`. + let text = + unsafe { std::str::from_utf8_unchecked(std::slice::from_raw_parts(massive_alloc, sz)) }; + let pool: rayon::ThreadPool = rayon::ThreadPoolBuilder::new() + .num_threads(1) + .build() + .unwrap(); + pool.install(|| { + let mut rope = Rope::new(); + rope.push_large(text); + }); + } + fn clip_offset(text: &str, mut offset: usize, bias: Bias) -> usize { while !text.is_char_boundary(offset) { match bias {