Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Commit

Permalink
Check arithmetic in malloc computations
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Dec 14, 2023
1 parent 9e054fb commit fd41ef6
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 5 deletions.
15 changes: 10 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ mod libc {
#[macro_use]
mod externs {
use crate::libc;
use crate::ops::{die, ForceAdd as _, ForceInto as _};
use alloc::alloc::{self as rust, Layout};
use core::mem::{self, MaybeUninit};
use core::ptr;
Expand All @@ -66,8 +67,10 @@ mod externs {
const MALLOC_ALIGN: usize = mem::align_of::<usize>();

pub unsafe fn malloc(size: libc::c_ulong) -> *mut libc::c_void {
let size = HEADER + size as usize;
let layout = Layout::from_size_align_unchecked(size, MALLOC_ALIGN);
let size = HEADER.force_add(size.force_into());
let layout = Layout::from_size_align(size, MALLOC_ALIGN)
.ok()
.unwrap_or_else(die);
let memory = rust::alloc(layout);
if memory.is_null() {
rust::handle_alloc_error(layout);
Expand All @@ -80,11 +83,13 @@ mod externs {
let mut memory = ptr.cast::<u8>().sub(HEADER);
let size = memory.cast::<usize>().read();
let layout = Layout::from_size_align_unchecked(size, MALLOC_ALIGN);
let new_size = HEADER + new_size as usize;
let new_size = HEADER.force_add(new_size.force_into());
let new_layout = Layout::from_size_align(new_size, MALLOC_ALIGN)
.ok()
.unwrap_or_else(die);
memory = rust::realloc(memory, layout, new_size);
if memory.is_null() {
let layout = Layout::from_size_align_unchecked(new_size, MALLOC_ALIGN);
rust::handle_alloc_error(layout);
rust::handle_alloc_error(new_layout);
}
memory.cast::<usize>().write(new_size);
memory.add(HEADER).cast()
Expand Down
23 changes: 23 additions & 0 deletions src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ impl ForceAdd for u64 {
}
}

impl ForceAdd for usize {
fn force_add(self, rhs: Self) -> Self {
self.checked_add(rhs).unwrap_or_else(die)
}
}

pub(crate) trait ForceMul: Sized {
fn force_mul(self, rhs: Self) -> Self;
}
Expand All @@ -48,6 +54,23 @@ impl ForceMul for u64 {
}
}

pub(crate) trait ForceInto {
fn force_into<U>(self) -> U
where
Self: TryInto<U>;
}

impl<T> ForceInto for T {
fn force_into<U>(self) -> U
where
Self: TryInto<U>,
{
<Self as TryInto<U>>::try_into(self)
.ok()
.unwrap_or_else(die)
}
}

// Deterministically abort on arithmetic overflow, instead of wrapping and
// continuing with invalid behavior.
//
Expand Down

0 comments on commit fd41ef6

Please sign in to comment.