Skip to content

Commit 172b6a6

Browse files
authored
Merge pull request mthom#3207 from Skgland/quote-fix-unquote-segv
"fix" segv from mthom#3198, mthom#3199, and mthom#3205
2 parents cd1ed10 + 129cca5 commit 172b6a6

File tree

6 files changed

+33
-15
lines changed

6 files changed

+33
-15
lines changed

src/machine/heap.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ impl Heap {
599599
pub(crate) fn with_cell_capacity(cap: usize) -> Result<Self, AllocError> {
600600
let ptr = unsafe {
601601
let layout = alloc::Layout::from_size_align(
602-
cap * size_of::<HeapCellValue>(),
602+
heap_index_checked!(cap).ok_or(AllocError)?,
603603
size_of::<HeapCellValue>(),
604604
)
605605
.unwrap();
@@ -623,7 +623,7 @@ impl Heap {
623623

624624
pub fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter<'_>, AllocError> {
625625
let section;
626-
let len = heap_index!(num_cells);
626+
let len = heap_index_checked!(num_cells).ok_or(AllocError)?;
627627

628628
loop {
629629
unsafe {
@@ -1148,7 +1148,9 @@ pub fn sized_iter_to_heap_list<SrcT: Into<HeapCellValue>>(
11481148
) -> Result<HeapCellValue, AllocError> {
11491149
if size > 0 {
11501150
let h = heap.cell_len();
1151-
let mut writer = heap.reserve(1 + 2 * size)?;
1151+
// not using checked_add for 1 + as the result of multiplying by 2 will be even and the largest representable usize is odd,
1152+
// so the addition cannot overflow
1153+
let mut writer = heap.reserve(1 + size.checked_mul(2).ok_or(AllocError)?)?;
11521154

11531155
writer.write_with(|section| {
11541156
for (idx, value) in values.enumerate() {

src/machine/machine_errors.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ impl ValidType {
7676

7777
#[derive(Debug, Clone, Copy)]
7878
pub(crate) enum ResourceError {
79-
FiniteMemory(HeapCellValue),
8079
OutOfFiles,
8180
}
8281

@@ -330,12 +329,6 @@ impl MachineState {
330329

331330
pub(super) fn resource_error(err: ResourceError) -> MachineError {
332331
let stub = match err {
333-
ResourceError::FiniteMemory(size_requested) => {
334-
functor!(
335-
atom!("resource_error"),
336-
[atom_as_cell((atom!("finite_memory"))), cell(size_requested)]
337-
)
338-
}
339332
ResourceError::OutOfFiles => {
340333
functor!(
341334
atom!("resource_error"),
@@ -778,9 +771,16 @@ impl MachineState {
778771

779772
// throw an error pre-allocated in the heap
780773
pub(super) fn throw_resource_error(&mut self, err: AllocError) {
774+
if self.throwing_resource_error {
775+
panic!("attempted to throw `error(resource_error(memory), [])` while attempting to throw `error(resource_error(memory), [])`");
776+
}
777+
self.throwing_resource_error = true;
778+
781779
self.registers[1] = str_loc_as_cell!(err.resource_error_offset(&mut self.heap));
782780
self.set_ball();
783781
self.unwind_stack();
782+
783+
self.throwing_resource_error = false;
784784
}
785785

786786
pub(super) fn throw_exception(&mut self, err: MachineStub) {

src/machine/machine_state.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ pub struct MachineState {
7474
pub(super) cp: usize,
7575
pub(super) attr_var_init: AttrVarInitializer,
7676
pub(super) fail: bool,
77+
pub throwing_resource_error: bool,
7778
pub heap: Heap,
7879
pub(super) mode: MachineMode,
7980
pub(crate) stack: Stack,

src/machine/machine_state_impl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ impl MachineState {
6767
unify_fn: MachineState::unify,
6868
bind_fn: MachineState::bind,
6969
run_cleaners_fn: |_| false,
70+
throwing_resource_error: false,
7071
}
7172
}
7273

src/machine/system_calls.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4371,16 +4371,15 @@ impl Machine {
43714371

43724372
#[inline(always)]
43734373
pub(crate) fn det_length_rundown(&mut self) -> CallResult {
4374-
let stub_gen = || functor_stub(atom!("length"), 2);
43754374
let len = self.deref_register(2);
43764375

43774376
let n = match Number::try_from((len, &self.machine_st.arena.f64_tbl)) {
43784377
Ok(Number::Fixnum(n)) => n.get_num() as usize,
43794378
Ok(Number::Integer(n)) => match (&*n).try_into() as Result<usize, _> {
43804379
Ok(n) => n,
43814380
Err(_) => {
4382-
let err = MachineState::resource_error(ResourceError::FiniteMemory(len));
4383-
return Err(self.machine_st.error_form(err, stub_gen()));
4381+
self.machine_st.throw_resource_error(AllocError);
4382+
return Ok(());
43844383
}
43854384
},
43864385
_ => {

src/macros.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,12 +470,27 @@ macro_rules! resource_error_call_result {
470470
};
471471
}
472472

473-
macro_rules! heap_index {
473+
macro_rules! heap_index_checked {
474474
($idx:expr) => {
475-
($idx) * std::mem::size_of::<HeapCellValue>()
475+
std::mem::size_of::<HeapCellValue>().checked_mul($idx)
476476
};
477477
}
478478

479+
pub(crate) use heap_index_checked;
480+
481+
macro_rules! heap_index {
482+
($idx:expr) => {{
483+
let idx = $idx;
484+
$crate::macros::heap_index_checked!(idx).unwrap_or_else(|| {
485+
panic!(
486+
"overflow while calculating heap index {idx} * {} > {}",
487+
std::mem::size_of::<HeapCellValue>(),
488+
usize::MAX,
489+
)
490+
})
491+
}};
492+
}
493+
479494
macro_rules! cell_index {
480495
($idx:expr) => {
481496
($idx) / std::mem::size_of::<HeapCellValue>()

0 commit comments

Comments
 (0)