Skip to content

Commit

Permalink
Fix UB caused by build_meta_predicate_clause reading OOB
Browse files Browse the repository at this point in the history
I don't know if that function is still needed, as making it return Default::default()
still passes all tests.

Nonetheless, this is now one less source of segfaults.

Fixes mthom#2763
  • Loading branch information
adri326 committed Jan 9, 2025
1 parent 2458005 commit 01d7430
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/machine/heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1198,12 +1198,14 @@ impl Index<usize> for Heap {
type Output = HeapCellValue;

fn index(&self, idx: usize) -> &Self::Output {
debug_assert!(idx < cell_index!(self.inner.byte_len));
unsafe { &*(self.inner.ptr as *const HeapCellValue).add(idx) }
}
}

impl IndexMut<usize> for Heap {
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
debug_assert!(idx < cell_index!(self.inner.byte_len));
unsafe { &mut *(self.inner.ptr as *mut HeapCellValue).add(idx) }
}
}
Expand Down
23 changes: 19 additions & 4 deletions src/machine/preprocessor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,13 +454,28 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
module_name: Atom,
arity: usize,
term: &TermWriteResult,
term: HeapCellValue,
meta_specs: Vec<MetaSpec>,
) -> IndexMap<usize, CodeIndex, FxBuildHasher> {
use crate::machine::heap::Heap;

let term_loc = read_heap_cell!(term,
(HeapCellValueTag::Str, loc) => {
loc
}
_ => {
panic!("build_meta_predicate_clause called with unsupported term ({term:?})");
}
);

debug_assert!(term_loc + arity < loader.machine_heap().cell_len());

let mut index_ptrs = IndexMap::with_hasher(FxBuildHasher::default());

for (subterm_loc, meta_spec) in (term.focus + 1..term.focus + arity + 1).zip(meta_specs) {
for (arg_index, meta_spec) in meta_specs.into_iter().enumerate() {
let subterm_loc = term_nth_arg(loader.machine_heap(), term_loc, arg_index + 1)
.expect("Arity mismatch");

if let MetaSpec::RequiresExpansionWithArgument(supp_args) = meta_spec {
let predicate_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);

Expand Down Expand Up @@ -561,7 +576,7 @@ pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let module_name = loader.payload.compilation_target.module_name();
let code_indices =
build_meta_predicate_clause(loader, module_name, arity, terms, meta_specs);
build_meta_predicate_clause(loader, module_name, arity, term, meta_specs);

return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx),
Expand Down Expand Up @@ -600,7 +615,7 @@ pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
if let ClauseType::Named(arity, name, idx) = ct {
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let code_indices =
build_meta_predicate_clause(loader, module_name, arity, &terms, meta_specs);
build_meta_predicate_clause(loader, module_name, arity, term, meta_specs);

return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx),
Expand Down

0 comments on commit 01d7430

Please sign in to comment.