Skip to content

Commit

Permalink
Use anyhow
Browse files Browse the repository at this point in the history
  • Loading branch information
smoelius committed Jul 14, 2024
1 parent 324d290 commit 6c6b6b0
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 47 deletions.
76 changes: 76 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cargo-afl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ homepage = "https://github.com/rust-fuzz/afl.rs"
edition = "2021"

[build-dependencies]
anyhow = { version = "1.0", features = ["backtrace"] }
clap = { version = "4.5", features = ["cargo", "derive"] }
fs_extra = "1.3"
home = "0.5"
Expand All @@ -22,6 +23,7 @@ tempfile = "3.10"
xdg = "2.5"

[dependencies]
anyhow = { version = "1.0", features = ["backtrace"] }
clap = { version = "4.5", features = ["cargo", "derive", "string"] }
fs_extra = "1.3"
home = "0.5"
Expand Down
16 changes: 10 additions & 6 deletions cargo-afl/src/common.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
#![deny(clippy::disallowed_macros, clippy::expect_used, clippy::unwrap_used)]

use anyhow::{Context, Result};
use std::env;
use std::ffi::OsStr;
use std::io::{Error, Result};
use std::path::{Path, PathBuf};

fn xdg_dir() -> Result<xdg::BaseDirectories> {
let afl_rustc_version = afl_rustc_version()?;
let prefix = Path::new("afl.rs")
.join(afl_rustc_version)
.join(pkg_version());
xdg::BaseDirectories::with_prefix(prefix).map_err(Error::other)
xdg::BaseDirectories::with_prefix(prefix).map_err(Into::into)
}

fn data_dir(dir_name: &str) -> Result<PathBuf> {
Expand All @@ -23,13 +23,13 @@ fn data_dir(dir_name: &str) -> Result<PathBuf> {
// don't change that for now for normal builds.
// smoelius: AFL++ is no longer built on docs.rs.
let xdg_dir = xdg_dir()?;
xdg_dir.create_data_directory(dir_name)
xdg_dir.create_data_directory(dir_name).map_err(Into::into)
}

const SHORT_COMMIT_HASH_LEN: usize = 7;

pub fn afl_rustc_version() -> Result<String> {
let version_meta = rustc_version::version_meta().map_err(Error::other)?;
let version_meta = rustc_version::version_meta()?;
let mut ret = String::from("rustc-");
ret.push_str(&version_meta.semver.to_string());
if let Some(commit_hash) = version_meta.commit_hash {
Expand Down Expand Up @@ -73,8 +73,12 @@ pub fn archive_file_path() -> Result<PathBuf> {
#[allow(dead_code)]
pub fn plugins_available() -> Result<bool> {
let afl_llvm_dir = afl_llvm_dir()?;
for result in afl_llvm_dir.read_dir()? {
let entry = result?;
for result in afl_llvm_dir
.read_dir()
.with_context(|| format!("could not read {afl_llvm_dir:?}"))?
{
let entry =
result.with_context(|| format!("could not read `DirEntry` in {afl_llvm_dir:?}"))?;
let file_name = entry.file_name();
if Path::new(&file_name).extension() == Some(OsStr::new("so")) {
return Ok(true);
Expand Down
69 changes: 28 additions & 41 deletions cargo-afl/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#![deny(clippy::disallowed_macros, clippy::expect_used, clippy::unwrap_used)]

use anyhow::{anyhow, Context, Result};
use clap::Parser;
use std::ffi::OsStr;
use std::io::{Error, Result};
use std::path::Path;
use std::process::{Command, ExitStatus, Stdio};

Expand Down Expand Up @@ -40,16 +40,16 @@ pub fn config(args: &Args) -> Result<()> {
let archive_file_path = common::archive_file_path()?;
if !args.force && archive_file_path.exists() && args.plugins == common::plugins_available()? {
let version = common::afl_rustc_version()?;
return Err(Error::other(format!(
return Err(anyhow!(
"AFL LLVM runtime was already built for Rust {version}; run `cargo afl config --build \
--force` to rebuild it."
)));
));
}

let afl_src_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join(AFL_SRC_PATH);
let afl_src_dir_str = &afl_src_dir.to_string_lossy();

let tempdir = tempfile::tempdir()?;
let tempdir = tempfile::tempdir().with_context(|| "could not create temporary directory")?;

if afl_src_dir.join(".git").is_dir() {
let success = Command::new("git")
Expand All @@ -58,7 +58,7 @@ pub fn config(args: &Args) -> Result<()> {
.as_ref()
.map_or(false, ExitStatus::success);
if !success {
return Err(Error::other("could not run 'git'"));
return Err(anyhow!("could not run 'git'"));
}
} else {
let _: u64 = fs_extra::dir::copy(
Expand All @@ -68,8 +68,7 @@ pub fn config(args: &Args) -> Result<()> {
content_only: true,
..Default::default()
},
)
.map_err(Error::other)?;
)?;
}

let work_dir = tempdir.path();
Expand All @@ -83,7 +82,7 @@ pub fn config(args: &Args) -> Result<()> {

let afl_dir = common::afl_dir()?;
let Some(dir) = afl_dir.parent().map(Path::to_path_buf) else {
return Err(Error::other("could not get afl dir parent"));
return Err(anyhow!("could not get afl dir parent"));
};
eprintln!("Artifacts written to {}", dir.display());

Expand Down Expand Up @@ -121,7 +120,7 @@ fn build_afl(args: &Args, work_dir: &Path) -> Result<()> {

let success = command.status().as_ref().map_or(false, ExitStatus::success);
if !success {
return Err(Error::other("could not run 'make install'"));
return Err(anyhow!("could not run 'make install'"));
}

Ok(())
Expand All @@ -130,7 +129,7 @@ fn build_afl(args: &Args, work_dir: &Path) -> Result<()> {
fn build_afl_llvm_runtime(args: &Args, work_dir: &Path) -> Result<()> {
let object_file_path = common::object_file_path()?;
let _: u64 = std::fs::copy(work_dir.join("afl-compiler-rt.o"), &object_file_path)
.map_err(|error| Error::other(format!("could not copy object file: {error}")))?;
.with_context(|| "could not copy object file")?;

let archive_file_path = common::archive_file_path()?;
let mut command = Command::new(AR_CMD);
Expand All @@ -146,28 +145,27 @@ fn build_afl_llvm_runtime(args: &Args, work_dir: &Path) -> Result<()> {

let success = command.status().as_ref().map_or(false, ExitStatus::success);
if !success {
return Err(Error::other("could not run 'ar'"));
return Err(anyhow!("could not run 'ar'"));
}

Ok(())
}

fn copy_afl_llvm_plugins(_args: &Args, work_dir: &Path) -> Result<()> {
// Iterate over the files in the directory.
for result in work_dir.read_dir()? {
let entry = result?;
for result in work_dir
.read_dir()
.with_context(|| format!("could not read {work_dir:?}"))?
{
let entry = result.with_context(|| format!("could not read `DirEntry` in {work_dir:?}"))?;
let file_name = entry.file_name();

// Get the file extension. Only copy the files that are shared objects.
if Path::new(&file_name).extension() == Some(OsStr::new("so")) {
// Attempt to copy the shared object file.
let afl_llvm_dir = common::afl_llvm_dir()?;
let _: u64 = std::fs::copy(work_dir.join(&file_name), afl_llvm_dir.join(&file_name))
.map_err(|error| {
Error::other(format!(
"could not copy shared object file {file_name:?}: {error}"
))
})?;
.with_context(|| format!("could not copy shared object file {file_name:?}"))?;
}
}

Expand All @@ -176,17 +174,17 @@ fn copy_afl_llvm_plugins(_args: &Args, work_dir: &Path) -> Result<()> {

fn check_llvm_and_get_config() -> Result<String> {
// Make sure we are on nightly for the -Z flags
let version_meta = rustc_version::version_meta().map_err(Error::other)?;
let version_meta = rustc_version::version_meta()?;
if version_meta.channel != rustc_version::Channel::Nightly {
return Err(Error::other(
return Err(anyhow!(
"cargo-afl must be compiled with nightly for the plugins feature",
));
}
let Some(llvm_version) = version_meta
.llvm_version
.map(|llvm_version| llvm_version.major.to_string())
else {
return Err(Error::other("could not get llvm version"));
return Err(anyhow!("could not get llvm version"));
};

// Fetch the llvm version of the rust toolchain and set the LLVM_CONFIG environment variable to the same version
Expand All @@ -200,33 +198,22 @@ fn check_llvm_and_get_config() -> Result<String> {
// check if llvm tools are installed and with the good version for the plugin compilation
let mut command = Command::new(&llvm_config);
command.args(["--version"]);
let out = match command.output() {
Ok(out) => out,
Err(error) => {
return Err(Error::other(format!(
"could not run {llvm_config} --version: {error}"
)));
}
};
let out = command
.output()
.with_context(|| format!("could not run {llvm_config} --version"))?;

let version = match String::from_utf8(out.stdout) {
Ok(version) => version,
Err(error) => {
return Err(Error::other(format!(
"could not convert {llvm_config} --version output to utf8: {error}"
)));
}
};
let version = String::from_utf8(out.stdout)
.with_context(|| format!("could not convert {llvm_config} --version output to utf8"))?;
let Some(major) = version.split('.').next() else {
return Err(Error::other(format!(
return Err(anyhow!(
"could not get major from {llvm_config} --version output",
)));
));
};
if major != llvm_version {
return Err(Error::other(format!(
return Err(anyhow!(
"{llvm_config} --version output does not contain expected major version \
({llvm_version})",
)));
));
}

Ok(llvm_config)
Expand Down

0 comments on commit 6c6b6b0

Please sign in to comment.