diff --git a/src/backport.rs b/src/backport.rs index c7751b29..4b67f56a 100644 --- a/src/backport.rs +++ b/src/backport.rs @@ -22,7 +22,9 @@ pub(crate) mod alloc { pub mod alloc { use std::mem; + use std::process; + #[derive(Copy, Clone)] pub struct Layout { size: usize, } @@ -47,5 +49,12 @@ pub(crate) mod alloc { let len_u16 = (layout.size + 1) / 2; unsafe { Vec::from_raw_parts(ptr as *mut u16, 0, len_u16) }; } + + pub fn handle_alloc_error(_layout: Layout) -> ! { + // This is unreachable because the alloc implementation above never + // returns null; Vec::reserve_exact would already have called std's + // internal handle_alloc_error. + process::abort(); + } } } diff --git a/src/identifier.rs b/src/identifier.rs index 170a4e05..fbe1df02 100644 --- a/src/identifier.rs +++ b/src/identifier.rs @@ -66,7 +66,7 @@ // repr, leaving it available as a niche for downstream code. For example this // allows size_of::() == size_of::>(). -use crate::alloc::alloc::{alloc, dealloc, Layout}; +use crate::alloc::alloc::{alloc, dealloc, handle_alloc_error, Layout}; use core::mem; use core::num::{NonZeroU64, NonZeroUsize}; use core::ptr::{self, NonNull}; @@ -123,6 +123,9 @@ impl Identifier { let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; // SAFETY: layout's size is nonzero. let ptr = unsafe { alloc(layout) }; + if ptr.is_null() { + handle_alloc_error(layout); + } let mut write = ptr; let mut varint_remaining = len; while varint_remaining > 0 { @@ -203,6 +206,9 @@ impl Clone for Identifier { let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; // SAFETY: layout's size is nonzero. let clone = unsafe { alloc(layout) }; + if clone.is_null() { + handle_alloc_error(layout); + } // SAFETY: new allocation cannot overlap the previous one (this was // not a realloc). The argument ptrs are readable/writeable // respectively for size bytes.