throw an error instead of allowing builtin modules to be overwritten (#2042)

This commit is contained in:
Mark
2023-09-25 19:20:11 -06:00
parent 172bb9e96a
commit 280ff8b5d0
3 changed files with 63 additions and 12 deletions

View File

@@ -9,7 +9,7 @@ use crate::parser::ast::*;
use fxhash::FxBuildHasher; use fxhash::FxBuildHasher;
use indexmap::IndexSet; use indexmap::IndexSet;
use ref_thread_local::RefThreadLocal; pub use ref_thread_local::RefThreadLocal;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fs::File; use std::fs::File;
@@ -1004,10 +1004,22 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
} }
pub(crate) fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) { pub(crate) fn add_module(
self.reset_in_situ_module(module_decl.clone(), &listing_src); &mut self,
module_decl: ModuleDecl,
listing_src: ListingSource,
) -> Result<(), SessionError> {
let module_name = module_decl.name; let module_name = module_decl.name;
if let Some(module) = self.wam_prelude.indices.modules.get(&module_name) {
if let ListingSource::DynamicallyGenerated = module.listing_src {
} else {
LS::err_on_builtin_module_overwrite(module_name)?;
}
}
self.reset_in_situ_module(module_decl.clone(), &listing_src);
let mut module = match self.wam_prelude.indices.modules.remove(&module_name) { let mut module = match self.wam_prelude.indices.modules.remove(&module_name) {
Some(mut module) => { Some(mut module) => {
module.listing_src = listing_src; module.listing_src = listing_src;
@@ -1045,6 +1057,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
self.wam_prelude.indices.modules.insert(module_name, module); self.wam_prelude.indices.modules.insert(module_name, module);
Ok(())
} }
pub(super) fn import_module(&mut self, module_name: Atom) -> Result<(), SessionError> { pub(super) fn import_module(&mut self, module_name: Atom) -> Result<(), SessionError> {

View File

@@ -265,6 +265,10 @@ pub trait LoadState<'a>: Sized {
loader: &Loader<'a, Self>, loader: &Loader<'a, Self>,
key: PredicateKey, key: PredicateKey,
) -> Result<(), SessionError>; ) -> Result<(), SessionError>;
fn err_on_builtin_module_overwrite(_module_name: Atom) -> Result<(), SessionError> {
Ok(())
}
} }
pub struct LiveLoadAndMachineState<'a> { pub struct LiveLoadAndMachineState<'a> {
@@ -353,6 +357,15 @@ impl<'a> LoadState<'a> for LiveLoadAndMachineState<'a> {
Ok(()) Ok(())
} }
#[inline]
fn err_on_builtin_module_overwrite(module_name: Atom) -> Result<(), SessionError> {
if LIBRARIES.borrow().contains_key(&*module_name.as_str()) {
Err(SessionError::CannotOverwriteBuiltInModule(module_name))
} else {
Ok(())
}
}
} }
impl<'a> LoadState<'a> for BootstrappingLoadState<'a> { impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
@@ -533,11 +546,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
self.add_meta_predicate_record(module_name, name, meta_specs); self.add_meta_predicate_record(module_name, name, meta_specs);
} }
Declaration::Module(module_decl) => { Declaration::Module(module_decl) => {
self.payload.compilation_target = CompilationTarget::Module(module_decl.name); let module_name = module_decl.name;
self.payload.compilation_target = CompilationTarget::Module(module_name);
self.payload.predicates.compilation_target = self.payload.compilation_target; self.payload.predicates.compilation_target = self.payload.compilation_target;
let listing_src = self.payload.term_stream.listing_src().clone(); let listing_src = self.payload.term_stream.listing_src().clone();
self.add_module(module_decl, listing_src); self.add_module(module_decl, listing_src)?;
} }
Declaration::NonCountedBacktracking(name, arity) => { Declaration::NonCountedBacktracking(name, arity) => {
self.payload.non_counted_bt_preds.insert((name, arity)); self.payload.non_counted_bt_preds.insert((name, arity));
@@ -1849,9 +1864,7 @@ impl Machine {
2, 2,
)?; )?;
let path = cell_as_atom!(self let path = cell_as_atom!(self.deref_register(2));
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[2])));
self.load_contexts self.load_contexts
.push(LoadContext::new(&*path.as_str(), stream)); .push(LoadContext::new(&*path.as_str(), stream));

View File

@@ -161,6 +161,26 @@ pub(crate) trait PermissionError {
) -> MachineError; ) -> MachineError;
} }
impl PermissionError for Atom {
fn permission_error(
self,
_machine_st: &mut MachineState,
index_atom: Atom,
perm: Permission,
) -> MachineError {
let stub = functor!(
atom!("permission_error"),
[atom(perm.as_atom()), atom(index_atom), cell(atom_as_cell!(self))]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
}
}
impl PermissionError for HeapCellValue { impl PermissionError for HeapCellValue {
fn permission_error( fn permission_error(
self, self,
@@ -459,7 +479,6 @@ impl MachineState {
pub(super) fn session_error(&mut self, err: SessionError) -> MachineError { pub(super) fn session_error(&mut self, err: SessionError) -> MachineError {
match err { match err {
SessionError::CannotOverwriteBuiltIn(key) => { SessionError::CannotOverwriteBuiltIn(key) => {
// SessionError::CannotOverwriteImport(pred_atom) => {
self.permission_error( self.permission_error(
Permission::Modify, Permission::Modify,
atom!("static_procedure"), atom!("static_procedure"),
@@ -468,10 +487,14 @@ impl MachineState {
.collect::<MachineStub>(), .collect::<MachineStub>(),
) )
} }
SessionError::CannotOverwriteBuiltInModule(module) => {
self.permission_error(
Permission::Modify,
atom!("static_module"),
module,
)
}
SessionError::ExistenceError(err) => self.existence_error(err), SessionError::ExistenceError(err) => self.existence_error(err),
// SessionError::InvalidFileName(filename) => {
// Self::existence_error(h, ExistenceError::Module(filename))
// }
SessionError::ModuleDoesNotContainExport(..) => { SessionError::ModuleDoesNotContainExport(..) => {
let error_atom = atom!("module_does_not_contain_claimed_export"); let error_atom = atom!("module_does_not_contain_claimed_export");
@@ -977,6 +1000,7 @@ pub enum ExistenceError {
pub enum SessionError { pub enum SessionError {
CompilationError(CompilationError), CompilationError(CompilationError),
CannotOverwriteBuiltIn(PredicateKey), CannotOverwriteBuiltIn(PredicateKey),
CannotOverwriteBuiltInModule(Atom),
ExistenceError(ExistenceError), ExistenceError(ExistenceError),
ModuleDoesNotContainExport(Atom, PredicateKey), ModuleDoesNotContainExport(Atom, PredicateKey),
ModuleCannotImportSelf(Atom), ModuleCannotImportSelf(Atom),