diff --git a/ethers-solc/src/config.rs b/ethers-solc/src/config.rs index 744c96783..e10eca345 100644 --- a/ethers-solc/src/config.rs +++ b/ethers-solc/src/config.rs @@ -272,3 +272,46 @@ impl fmt::Debug for ArtifactOutput { } } } + +use std::convert::TryFrom; + +#[derive(Clone, Debug)] +/// Helper struct for serializing `--allow-paths` arguments to Solc +/// +/// From the [Solc docs](https://docs.soliditylang.org/en/v0.8.9/using-the-compiler.html#base-path-and-import-remapping): +/// For security reasons the compiler has restrictions on what directories it can access. +/// Directories of source files specified on the command line and target paths of +/// remappings are automatically allowed to be accessed by the file reader, +/// but everything else is rejected by default. Additional paths (and their subdirectories) +/// can be allowed via the --allow-paths /sample/path,/another/sample/path switch. +/// Everything inside the path specified via --base-path is always allowed. +pub struct AllowedLibPaths(Vec); + +impl fmt::Display for AllowedLibPaths { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let lib_paths = self + .0 + .iter() + .filter(|path| PathBuf::from(path).exists()) + .map(|path| path.into_os_string().into_string().unwrap()) + .collect::>() + .join(","); + write!(f, "{}", lib_paths) + } +} + +impl> TryFrom> for AllowedLibPaths { + type Error = std::io::Error; + + fn try_from(libs: Vec) -> std::result::Result { + let libs = libs + .into_iter() + .map(|lib| { + let path: PathBuf = lib.into(); + let lib = std::fs::canonicalize(path)?; + Ok(lib) + }) + .collect::, std::io::Error>>()?; + Ok(AllowedLibPaths(libs)) + } +} diff --git a/ethers-solc/src/lib.rs b/ethers-solc/src/lib.rs index eb5d03f80..8e9b7bb3a 100644 --- a/ethers-solc/src/lib.rs +++ b/ethers-solc/src/lib.rs @@ -11,7 +11,7 @@ mod compile; pub use compile::*; mod config; -pub use config::{ArtifactOutput, ProjectPathsConfig, SolcConfig}; +pub use config::{AllowedLibPaths, ArtifactOutput, ProjectPathsConfig, SolcConfig}; use crate::{artifacts::Source, cache::SolFilesCache}; @@ -40,6 +40,8 @@ pub struct Project { pub artifacts: ArtifactOutput, /// Errors/Warnings which match these error codes are not going to be logged pub ignored_error_codes: Vec, + /// The paths which will be allowed for library inclusion + pub allowed_lib_paths: AllowedLibPaths, } impl Project { @@ -116,8 +118,12 @@ impl Project { let version = Solc::detect_version(&source)?; // gets the solc binary for that version, it is expected tha this will succeed // AND find the solc since it was installed right above - let solc = Solc::find_svm_installed_version(version.to_string())? + let mut solc = Solc::find_svm_installed_version(version.to_string())? .expect("solc should have been installed"); + // configure solc + solc.args.push("--allow-paths".to_string()); + solc.args.push(self.allowed_lib_paths.to_string()); + let entry = sources_by_version.entry(solc).or_insert_with(BTreeMap::new); entry.insert(path, source); }