Merge pull request #3207 from Skgland/quote-fix-unquote-segv
"fix" segv from #3198, #3199, and #3205
This commit is contained in:
@@ -599,7 +599,7 @@ impl Heap {
|
|||||||
pub(crate) fn with_cell_capacity(cap: usize) -> Result<Self, AllocError> {
|
pub(crate) fn with_cell_capacity(cap: usize) -> Result<Self, AllocError> {
|
||||||
let ptr = unsafe {
|
let ptr = unsafe {
|
||||||
let layout = alloc::Layout::from_size_align(
|
let layout = alloc::Layout::from_size_align(
|
||||||
cap * size_of::<HeapCellValue>(),
|
heap_index_checked!(cap).ok_or(AllocError)?,
|
||||||
size_of::<HeapCellValue>(),
|
size_of::<HeapCellValue>(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -623,7 +623,7 @@ impl Heap {
|
|||||||
|
|
||||||
pub fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter<'_>, AllocError> {
|
pub fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter<'_>, AllocError> {
|
||||||
let section;
|
let section;
|
||||||
let len = heap_index!(num_cells);
|
let len = heap_index_checked!(num_cells).ok_or(AllocError)?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -1148,7 +1148,9 @@ pub fn sized_iter_to_heap_list<SrcT: Into<HeapCellValue>>(
|
|||||||
) -> Result<HeapCellValue, AllocError> {
|
) -> Result<HeapCellValue, AllocError> {
|
||||||
if size > 0 {
|
if size > 0 {
|
||||||
let h = heap.cell_len();
|
let h = heap.cell_len();
|
||||||
let mut writer = heap.reserve(1 + 2 * size)?;
|
// not using checked_add for 1 + as the result of multiplying by 2 will be even and the largest representable usize is odd,
|
||||||
|
// so the addition cannot overflow
|
||||||
|
let mut writer = heap.reserve(1 + size.checked_mul(2).ok_or(AllocError)?)?;
|
||||||
|
|
||||||
writer.write_with(|section| {
|
writer.write_with(|section| {
|
||||||
for (idx, value) in values.enumerate() {
|
for (idx, value) in values.enumerate() {
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ impl ValidType {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub(crate) enum ResourceError {
|
pub(crate) enum ResourceError {
|
||||||
FiniteMemory(HeapCellValue),
|
|
||||||
OutOfFiles,
|
OutOfFiles,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,12 +329,6 @@ impl MachineState {
|
|||||||
|
|
||||||
pub(super) fn resource_error(err: ResourceError) -> MachineError {
|
pub(super) fn resource_error(err: ResourceError) -> MachineError {
|
||||||
let stub = match err {
|
let stub = match err {
|
||||||
ResourceError::FiniteMemory(size_requested) => {
|
|
||||||
functor!(
|
|
||||||
atom!("resource_error"),
|
|
||||||
[atom_as_cell((atom!("finite_memory"))), cell(size_requested)]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ResourceError::OutOfFiles => {
|
ResourceError::OutOfFiles => {
|
||||||
functor!(
|
functor!(
|
||||||
atom!("resource_error"),
|
atom!("resource_error"),
|
||||||
@@ -778,9 +771,16 @@ impl MachineState {
|
|||||||
|
|
||||||
// throw an error pre-allocated in the heap
|
// throw an error pre-allocated in the heap
|
||||||
pub(super) fn throw_resource_error(&mut self, err: AllocError) {
|
pub(super) fn throw_resource_error(&mut self, err: AllocError) {
|
||||||
|
if self.throwing_resource_error {
|
||||||
|
panic!("attempted to throw `error(resource_error(memory), [])` while attempting to throw `error(resource_error(memory), [])`");
|
||||||
|
}
|
||||||
|
self.throwing_resource_error = true;
|
||||||
|
|
||||||
self.registers[1] = str_loc_as_cell!(err.resource_error_offset(&mut self.heap));
|
self.registers[1] = str_loc_as_cell!(err.resource_error_offset(&mut self.heap));
|
||||||
self.set_ball();
|
self.set_ball();
|
||||||
self.unwind_stack();
|
self.unwind_stack();
|
||||||
|
|
||||||
|
self.throwing_resource_error = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn throw_exception(&mut self, err: MachineStub) {
|
pub(super) fn throw_exception(&mut self, err: MachineStub) {
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ pub struct MachineState {
|
|||||||
pub(super) cp: usize,
|
pub(super) cp: usize,
|
||||||
pub(super) attr_var_init: AttrVarInitializer,
|
pub(super) attr_var_init: AttrVarInitializer,
|
||||||
pub(super) fail: bool,
|
pub(super) fail: bool,
|
||||||
|
pub throwing_resource_error: bool,
|
||||||
pub heap: Heap,
|
pub heap: Heap,
|
||||||
pub(super) mode: MachineMode,
|
pub(super) mode: MachineMode,
|
||||||
pub(crate) stack: Stack,
|
pub(crate) stack: Stack,
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ impl MachineState {
|
|||||||
unify_fn: MachineState::unify,
|
unify_fn: MachineState::unify,
|
||||||
bind_fn: MachineState::bind,
|
bind_fn: MachineState::bind,
|
||||||
run_cleaners_fn: |_| false,
|
run_cleaners_fn: |_| false,
|
||||||
|
throwing_resource_error: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4371,7 +4371,6 @@ impl Machine {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn det_length_rundown(&mut self) -> CallResult {
|
pub(crate) fn det_length_rundown(&mut self) -> CallResult {
|
||||||
let stub_gen = || functor_stub(atom!("length"), 2);
|
|
||||||
let len = self.deref_register(2);
|
let len = self.deref_register(2);
|
||||||
|
|
||||||
let n = match Number::try_from((len, &self.machine_st.arena.f64_tbl)) {
|
let n = match Number::try_from((len, &self.machine_st.arena.f64_tbl)) {
|
||||||
@@ -4379,8 +4378,8 @@ impl Machine {
|
|||||||
Ok(Number::Integer(n)) => match (&*n).try_into() as Result<usize, _> {
|
Ok(Number::Integer(n)) => match (&*n).try_into() as Result<usize, _> {
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let err = MachineState::resource_error(ResourceError::FiniteMemory(len));
|
self.machine_st.throw_resource_error(AllocError);
|
||||||
return Err(self.machine_st.error_form(err, stub_gen()));
|
return Ok(());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
|||||||
@@ -470,12 +470,27 @@ macro_rules! resource_error_call_result {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! heap_index {
|
macro_rules! heap_index_checked {
|
||||||
($idx:expr) => {
|
($idx:expr) => {
|
||||||
($idx) * std::mem::size_of::<HeapCellValue>()
|
std::mem::size_of::<HeapCellValue>().checked_mul($idx)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) use heap_index_checked;
|
||||||
|
|
||||||
|
macro_rules! heap_index {
|
||||||
|
($idx:expr) => {{
|
||||||
|
let idx = $idx;
|
||||||
|
$crate::macros::heap_index_checked!(idx).unwrap_or_else(|| {
|
||||||
|
panic!(
|
||||||
|
"overflow while calculating heap index {idx} * {} > {}",
|
||||||
|
std::mem::size_of::<HeapCellValue>(),
|
||||||
|
usize::MAX,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! cell_index {
|
macro_rules! cell_index {
|
||||||
($idx:expr) => {
|
($idx:expr) => {
|
||||||
($idx) / std::mem::size_of::<HeapCellValue>()
|
($idx) / std::mem::size_of::<HeapCellValue>()
|
||||||
|
|||||||
Reference in New Issue
Block a user