Skip to content

Commit

Permalink
🧩 Implement PhinkEnv enum for environment variables
Browse files Browse the repository at this point in the history
Refactored environment variable management by introducing the `PhinkEnv` enum, simplifying and centralizing the handling of key environment variables. Additionally, moved the error formatting function to a more appropriate module and streamlined various function calls to use the `PhinkEnv` enum.

Signed-off-by: Kevin Valerio <kevin@srlabs.de>
  • Loading branch information
kevin-valerio committed Sep 5, 2024
1 parent 02ea402 commit 3719dbe
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 77 deletions.
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[toolchain]
channel = "nightly-2024-08-13"
channel = "nightly"
components = ["rustfmt", "cargo", "rustc", "rust-std", "clippy"]
targets = [
"aarch64-apple-darwin", # macOS on ARM architecture
Expand Down
52 changes: 52 additions & 0 deletions src/cli/env.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::fmt::Display;

#[derive(Debug, Clone, Copy)]
pub enum PhinkEnv {
FuzzingWithConfig,
FromZiggy,
CargoManifestDir,
AflForkServerTimeout,
AflDebug,
AflLLVMAllowList,
}

impl Display for PhinkEnv {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
PhinkEnv::FuzzingWithConfig => "PHINK_START_FUZZING_WITH_CONFIG",
PhinkEnv::FromZiggy => "PHINK_FROM_ZIGGY",
PhinkEnv::CargoManifestDir => "CARGO_MANIFEST_DIR",
PhinkEnv::AflForkServerTimeout => "AFL_FORKSRV_INIT_TMOUT",
PhinkEnv::AflDebug => "AFL_DEBUG",
PhinkEnv::AflLLVMAllowList => "AFL_LLVM_ALLOWLIST",
})
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_phink_env_display() {
assert_eq!(
PhinkEnv::FuzzingWithConfig.to_string(),
"PHINK_START_FUZZING_WITH_CONFIG"
);
assert_eq!(PhinkEnv::FromZiggy.to_string(), "PHINK_FROM_ZIGGY");
assert_eq!(PhinkEnv::CargoManifestDir.to_string(), "CARGO_MANIFEST_DIR");
}

#[test]
fn test_phink_env_debug() {
assert_eq!(
format!("{:?}", PhinkEnv::FuzzingWithConfig),
"StartFuzzingWithConfig"
);
assert_eq!(format!("{:?}", PhinkEnv::FromZiggy), "FromZiggy");
assert_eq!(
format!("{:?}", PhinkEnv::CargoManifestDir),
"CargoManifestDir"
);
}
}
34 changes: 34 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,37 @@
use colored::Colorize;
use std::backtrace::BacktraceStatus;

pub mod config;
pub mod env;
pub mod ui;
pub mod ziggy;

/// Prints `anyhow` errors correctly in the Phink style
///
/// # Argument
/// * `e`: The `anyhow::Error` to pretty-print
///
/// returns: `String`
///
/// # Example
/// `eprintln!("{}", format_error(e));`
pub fn format_error(e: anyhow::Error) -> String {
let mut message = format!("\n{}: {}\n", "Phink got an error...".red().bold(), e);

if e.backtrace().status() == BacktraceStatus::Captured {
message = format!(
"{}\n{}\n{}\n",
message,
"Backtrace ->".yellow(),
e.backtrace()
)
}

let mut source = e.source();
while let Some(cause) = source {
message = format!("{}\n\n{}: {}", message, "Caused by".cyan().bold(), cause);
source = cause.source();
}

message
}
43 changes: 23 additions & 20 deletions src/cli/ziggy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ use crate::cli::{
},
PhinkFiles,
},
env::{
PhinkEnv,
PhinkEnv::{
AflDebug,
AflForkServerTimeout,
},
},
ui,
};
use std::{
Expand All @@ -34,6 +41,11 @@ use std::{
Stdio,
},
};
use PhinkEnv::{
AflLLVMAllowList,
FromZiggy,
FuzzingWithConfig,
};

pub const AFL_DEBUG: &str = "1";
pub const AFL_FORKSRV_INIT_TMOUT: &str = "10000000";
Expand Down Expand Up @@ -70,7 +82,7 @@ impl ZiggyConfig {
pub fn parse(config_str: String) -> Self {
let config: Self = serde_json::from_str(&config_str).expect("❌ Failed to parse config");
if config.config.verbose {
println!("πŸ–¨οΈ Using PHINK_START_FUZZING_WITH_CONFIG = {config_str}",);
println!("πŸ–¨οΈ Using {} = {config_str}", FuzzingWithConfig);
}
config
}
Expand Down Expand Up @@ -102,9 +114,9 @@ impl ZiggyConfig {
let command_builder = binding
.arg("ziggy")
.arg(ziggy_command)
.env("PHINK_FROM_ZIGGY", "1")
.env("AFL_FORKSRV_INIT_TMOUT", AFL_FORKSRV_INIT_TMOUT)
.env("AFL_DEBUG", AFL_DEBUG)
.env(FromZiggy.to_string(), "1")
.env(AflForkServerTimeout.to_string(), AFL_FORKSRV_INIT_TMOUT)
.env(AflDebug.to_string(), AFL_DEBUG)
.stdout(Stdio::null())
.stderr(Stdio::null());

Expand Down Expand Up @@ -132,7 +144,7 @@ impl ZiggyConfig {
if cfg!(not(target_os = "macos")) {
let allowlist = PhinkFiles::new(self.config.fuzz_output.clone().unwrap_or_default())
.path(AllowlistPath);
command_builder.env("AFL_LLVM_ALLOWLIST", allowlist.canonicalize()?);
command_builder.env(AflLLVMAllowList.to_string(), allowlist.canonicalize()?);
}
Ok(())
}
Expand Down Expand Up @@ -167,10 +179,7 @@ impl ZiggyConfig {
))
}

let fuzz_config = vec![(
"PHINK_START_FUZZING_WITH_CONFIG".to_string(),
serde_json::to_string(self)?,
)];
let fuzz_config = vec![(FuzzingWithConfig.to_string(), serde_json::to_string(self)?)];

self.start(
ZiggyCommand::Fuzz(self.config.show_ui),
Expand All @@ -183,10 +192,7 @@ impl ZiggyConfig {
self.start(
ZiggyCommand::Cover,
vec![],
vec![(
"PHINK_START_FUZZING_WITH_CONFIG".into(),
serde_json::to_string(self)?,
)],
vec![(FuzzingWithConfig.to_string(), serde_json::to_string(self)?)],
)?;
Ok(())
}
Expand All @@ -203,10 +209,7 @@ impl ZiggyConfig {
self.start(
ZiggyCommand::Run,
vec![],
vec![(
"PHINK_START_FUZZING_WITH_CONFIG".into(),
serde_json::to_string(self)?,
)],
vec![(FuzzingWithConfig.to_string(), serde_json::to_string(self)?)],
)?;
Ok(())
}
Expand All @@ -217,7 +220,7 @@ impl ZiggyConfig {
.path(AllowlistPath);

if allowlist_path.exists() {
println!("❗ AFL_LLVM_ALLOWLIST already exists... skipping");
println!("❗ {} already exists... skipping", AflLLVMAllowList);
return Ok(());
}

Expand All @@ -229,7 +232,7 @@ impl ZiggyConfig {
writeln!(allowlist_file, "fun: {}", func)?;
}

println!("βœ… AFL_LLVM_ALLOWLIST created successfully");
println!("βœ… {} created successfully", AflLLVMAllowList);
Ok(())
}
}
Expand Down Expand Up @@ -353,7 +356,7 @@ mod tests {
.collect();

assert!(env_vars.contains(&(
"AFL_LLVM_ALLOWLIST".to_string(),
AflLLVMAllowList.to_string(),
allowlist_path.to_str().unwrap().to_string()
)));
}
Expand Down
31 changes: 21 additions & 10 deletions src/instrumenter/instrumentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub struct InkFilesPath {
pub wasm_path: PathBuf,
pub specs_path: PathBuf,
}
/// Invokes `println!` only if `verbose` is `true`
macro_rules! phink_log {
($self:expr, $($arg:tt)*) => {
if $self.to_owned().verbose() {
Expand All @@ -68,7 +69,8 @@ impl Instrumenter {
}

pub fn find(&self) -> anyhow::Result<InkFilesPath> {
let wasm_path = fs::read_dir(&self.z_config.contract_path.join("target/ink/"))
let c_path = self.to_owned().z_config.contract_path;
let wasm_path = fs::read_dir(c_path.join("target/ink/"))
.with_context(|| {
format!(
"It seems that your contract is not compiled into `target/ink`. \
Expand All @@ -79,7 +81,7 @@ impl Instrumenter {
.instrumented_path()
.to_str()
.unwrap(),
self.z_config.contract_path.to_str().unwrap(),
c_path.to_str().unwrap(),
)
})?
.filter_map(|entry| {
Expand Down Expand Up @@ -111,25 +113,35 @@ impl Instrumenter {
bail!("There was probably a fork issue, as {p_display} doesn't exist.")
}

let status = Command::new("cargo")
.current_dir(path.to_owned())
let mut build = Command::new("cargo")
.current_dir(path.as_path())
.args(["contract", "build", "--features=phink"])
.status()?;
.spawn()?;

phink_log!(self, "βœ‚οΈ Compiling {}...", p_display);

let status = build.wait()?;

if !status.success() {
bail!(
"πŸ™… It seems that your instrumented smart contract did not compile properly. \
Please go to {p_display}, edit the source code, and run cargo contract build again\
({status}).",
Please go to {p_display}, edit the source code, and run `cargo contract build` again \
({status}).",
)
}

println!(
"\n🀞 Contract '{}' has been instrumented and compiled.\n🀞 You can find the instrumented contract in '{p_display}./'",
self.z_config.contract_path.display(),
);

Ok(())
}

fn fork(self) -> anyhow::Result<PathBuf> {
let new_dir = &self.to_owned().z_config.instrumented_path();

println!("πŸ—οΈ Creating new directory: {:?}", new_dir);
phink_log!(self, "πŸ—οΈ Creating new directory: {:?}", new_dir);

fs::create_dir_all(new_dir)
.with_context(|| format!("πŸ™… Failed to create directory: {}", new_dir.display()))?;
Expand All @@ -150,7 +162,7 @@ impl Instrumenter {
);

if entry.path().is_dir() {
println!("πŸ“‚ Creating subdirectory: {:?}", target_path);
phink_log!(self, "πŸ“‚ Creating subdirectory: {:?}", target_path);
fs::create_dir_all(&target_path)?;
} else {
phink_log!(
Expand Down Expand Up @@ -310,7 +322,6 @@ mod tests {
self,
File,
},
io::Read,
};
use tempfile::{
tempdir,
Expand Down
1 change: 1 addition & 0 deletions src/instrumenter/instrumented_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ impl InstrumentedPath {
}

#[deprecated]

pub fn clean() -> anyhow::Result<()> {
let dirs_to_remove =
Self::get_dirs_to_remove(Path::new("/tmp"), DEFAULT_PATH_PATTERN_INSTRUMENTEDPATH)?;
Expand Down
Loading

0 comments on commit 3719dbe

Please sign in to comment.