Skip to content

Commit

Permalink
Rework features
Browse files Browse the repository at this point in the history
  • Loading branch information
smoelius committed Oct 5, 2023
1 parent d62d9f9 commit 163fee8
Show file tree
Hide file tree
Showing 19 changed files with 108 additions and 155 deletions.
2 changes: 1 addition & 1 deletion cargo-test-fuzz/src/bin/cargo_test_fuzz/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ mod tests {
#[allow(clippy::unwrap_used)]
cargo_test_fuzz(&[
"--features",
&("test-fuzz/".to_owned() + test_fuzz::serde_format().as_feature()),
&("test-fuzz/".to_owned() + test_fuzz::serde_format::as_feature()),
"--no-run",
"--no-instrumentation",
"target",
Expand Down
15 changes: 8 additions & 7 deletions cargo-test-fuzz/tests/fuzz_generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ const TIMEOUT: &str = "60";
fn fuzz_foo_qwerty() {
// smoelius: When `bincode` is enabled, `cargo-afl` fails because "the program crashed with one
// of the test cases provided."
// smoelius: `to_string` is used here because `SerdeFormat` won't necessarily contain the
// `Bincode` variant.
if serde_format().to_string() == "Bincode" {
fuzz("test_foo_qwerty", 2);
} else {
fuzz("test_foo_qwerty", 1);
};
fuzz(
"test_foo_qwerty",
if serde_format::serializes_variant_names() {
1
} else {
2
},
);
}

#[cfg_attr(dylint_lib = "general", allow(non_thread_safe_call_in_test))]
Expand Down
1 change: 0 additions & 1 deletion docs/crates.dot
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ digraph {
"cargo-test-fuzz" -> "internal"
"cargo-test-fuzz" -> "test-fuzz"
"cargo-test-fuzz" -> "testing"
"macro" -> "internal"
"macro-generated-code" -> "test-fuzz"
"runtime" -> "internal"
"test-fuzz" -> "internal"
Expand Down
19 changes: 14 additions & 5 deletions internal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,24 @@ authors = ["Samuel E. Moelius III <sam@moeli.us>"]
license = "AGPL-3.0 WITH mif-exception"
repository = "https://github.com/trailofbits/test-fuzz"

# smoelius: https://github.com/rust-lang/cargo/issues/1839
# Because of the above issue, the crate for the default format (bincode) must be included regardless
# of whether it is selected. A test-fuzz test (`link`) verifies that the crate's code is not linked
# in when another format is selected.

[dependencies]
cargo_metadata = "0.18"
proc-macro2 = "1.0"
quote = "1.0"
serde = "1.0"
strum_macros = "0.25"

bincode = "1.3"
cbor4ii = { version = "0.3", features = ["serde1", "use_std"], optional = true }
serde_cbor = { version = "0.11", optional = true }

[features]
__auto_concretize = []
__serde_bincode = []
__serde_cbor = []
__serde_cbor4ii = []
__serde_cbor = ["serde_cbor"]
__serde_cbor4ii = ["cbor4ii"]

[package.metadata.cargo-udeps.ignore]
normal = ["bincode"]
3 changes: 1 addition & 2 deletions internal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ pub use auto_concretize::enabled as auto_concretize_enabled;

pub mod dirs;

mod serde_format;
pub use serde_format::*;
pub mod serde_format;
105 changes: 68 additions & 37 deletions internal/src/serde_format.rs
Original file line number Diff line number Diff line change
@@ -1,56 +1,87 @@
#![allow(clippy::use_self)]
use serde::{de::DeserializeOwned, Serialize};
use std::io::Read;

use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote, ToTokens, TokenStreamExt};
use strum_macros::Display;

#[derive(Copy, Clone, Debug, Display, Eq, PartialEq)]
pub enum SerdeFormat {
#[cfg(any(serde_default, feature = "__serde_bincode"))]
Bincode,
#[cfg(feature = "__serde_cbor")]
Cbor,
#[cfg(feature = "__serde_cbor4ii")]
Cbor4ii,
}
#[cfg(any(serde_default, feature = "__serde_bincode"))]
const BYTE_LIMIT: u64 = 1024 * 1024 * 1024;

#[allow(clippy::vec_init_then_push)]
#[must_use]
pub fn serde_format() -> SerdeFormat {
pub fn as_feature() -> &'static str {
let mut formats = vec![];

#[cfg(any(serde_default, feature = "__serde_bincode"))]
formats.push(SerdeFormat::Bincode);
formats.push("serde_bincode");

#[cfg(feature = "__serde_cbor")]
formats.push(SerdeFormat::Cbor);
formats.push("serde_cbor");

#[cfg(feature = "__serde_cbor4ii")]
formats.push(SerdeFormat::Cbor4ii);
formats.push("serde_cbor4ii");

assert!(
formats.len() <= 1,
"{}",
"Multiple serde formats selected: {formats:?}"
);

formats.pop().expect("No serde format selected")
}

impl SerdeFormat {
#[must_use]
pub fn as_feature(self) -> &'static str {
match self {
#[cfg(any(serde_default, feature = "__serde_bincode"))]
Self::Bincode => "serde_bincode",
#[cfg(feature = "__serde_cbor")]
Self::Cbor => "serde_cbor",
#[cfg(feature = "__serde_cbor4ii")]
Self::Cbor4ii => "serde_cbor4ii",
}
}
#[must_use]
pub fn serializes_variant_names() -> bool {
#[cfg(any(serde_default, feature = "__serde_bincode"))]
return false;

#[cfg(feature = "__serde_cbor")]
return true;

#[cfg(feature = "__serde_cbor4ii")]
return true;
}

pub fn serialize<T: Serialize>(args: &T) -> Vec<u8> {
#[cfg(any(serde_default, feature = "__serde_bincode"))]
return {
use bincode::Options;
// smoelius: From
// https://github.com/bincode-org/bincode/blob/c44b5e364e7084cdbabf9f94b63a3c7f32b8fb68/src/lib.rs#L102-L103 :
// /// **Warning:** the default configuration used by [`bincode::serialize`] is not
// /// the same as that used by the `DefaultOptions` struct. ...
// The point is that `bincode::serialize(..)` and `bincode::options().serialize(..)` use
// different encodings, even though the latter uses "default" options.
bincode::options()
.with_limit(BYTE_LIMIT)
.serialize(args)
.unwrap()
};

#[cfg(feature = "__serde_cbor")]
return serde_cbor::to_vec(args).unwrap();

#[cfg(feature = "__serde_cbor4ii")]
return {
let mut data = Vec::new();
cbor4ii::serde::to_writer(&mut data, args).unwrap();
data
};
}

impl ToTokens for SerdeFormat {
fn to_tokens(&self, tokens: &mut TokenStream) {
let ident = Ident::new(&self.to_string(), Span::call_site());
tokens.append_all(quote! {
test_fuzz::SerdeFormat::#ident
});
}
pub fn deserialize<T: DeserializeOwned, R: Read>(reader: R) -> Option<T> {
#[cfg(any(serde_default, feature = "__serde_bincode"))]
return {
use bincode::Options;
bincode::options()
.with_limit(BYTE_LIMIT)
.deserialize_from(reader)
.ok()
};

#[cfg(feature = "__serde_cbor")]
return serde_cbor::from_reader(reader).ok();

#[cfg(feature = "__serde_cbor4ii")]
return {
let reader = std::io::BufReader::new(reader);
cbor4ii::serde::from_reader(reader).ok()
};
}
7 changes: 2 additions & 5 deletions macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@ subprocess = "0.2"
syn = { version = "2.0", features = ["full", "parsing", "visit", "visit-mut"] }
toolchain_find = "0.4"

internal = { path = "../internal", package = "test-fuzz-internal", version = "=4.0.1" }
internal = { path = "../internal", package = "test-fuzz-internal", version = "=4.0.1", optional = true }

[features]
__auto_concretize = []
__auto_concretize = ["internal"]
__persistent = []
__serde_bincode = ["internal/__serde_bincode"]
__serde_cbor = ["internal/__serde_cbor"]
__serde_cbor4ii = ["internal/__serde_cbor4ii"]
8 changes: 0 additions & 8 deletions macro/build.rs

This file was deleted.

6 changes: 2 additions & 4 deletions macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#![cfg_attr(feature = "__auto_concretize", feature(proc_macro_span))]

use darling::{ast::NestedMeta, FromMeta};
use internal::serde_format;
use itertools::MultiUnzip;
use once_cell::sync::Lazy;
use proc_macro::TokenStream;
Expand Down Expand Up @@ -453,7 +452,6 @@ fn map_method_or_fn(
)
};

let serde_format = serde_format();
let write_concretizations = quote! {
let impl_concretization = [
#(#impl_ty_names),*
Expand Down Expand Up @@ -628,7 +626,7 @@ fn map_method_or_fn(
let args = Args(
#(#args_is),*
);
test_fuzz::runtime::write_args(#serde_format, &args);
test_fuzz::runtime::write_args(&args);
}

struct UsingReader<R>(R);
Expand All @@ -639,7 +637,7 @@ fn map_method_or_fn(
struct Args #ty_generics (
#(#pub_arg_tys),*
) #args_where_clause;
let args = test_fuzz::runtime::read_args::<Args #ty_generics_as_turbofish, _>(#serde_format, reader);
let args = test_fuzz::runtime::read_args::<Args #ty_generics_as_turbofish, _>(reader);
args.map(|args| #mod_ident :: Args(
#(#args_is),*
))
Expand Down
16 changes: 0 additions & 16 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,10 @@ authors = ["Samuel E. Moelius III <sam@moeli.us>"]
license = "AGPL-3.0 WITH mif-exception"
repository = "https://github.com/trailofbits/test-fuzz"

# smoelius: https://github.com/rust-lang/cargo/issues/1839
# Because of the above issue, the crate for the default format (bincode) must be included regardless
# of whether it is selected. A test-fuzz test (`link`) verifies that the crate's code is not linked
# in when another format is selected.

[dependencies]
bincode = "1.3"
cbor4ii = { version = "0.3", features = ["serde1", "use_std"], optional = true }
hex = "0.4"
num-traits = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_cbor = { version = "0.11", optional = true }
sha-1 = "0.10"

internal = { path = "../internal", package = "test-fuzz-internal", version = "=4.0.1" }

[features]
__serde_bincode = []
__serde_cbor = ["serde_cbor"]
__serde_cbor4ii = ["cbor4ii"]

[package.metadata.cargo-udeps.ignore]
normal = ["bincode"]
8 changes: 0 additions & 8 deletions runtime/build.rs

This file was deleted.

53 changes: 5 additions & 48 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use internal::{
concretizations_directory_from_args_type, corpus_directory_from_args_type,
impl_concretizations_directory_from_args_type,
},
SerdeFormat,
serde_format,
};
use serde::{de::DeserializeOwned, Serialize};
use sha1::{Digest, Sha1};
Expand All @@ -21,9 +21,6 @@ pub use num_traits;

pub mod traits;

#[cfg(any(serde_default, feature = "__serde_bincode"))]
const BYTE_LIMIT: u64 = 1024 * 1024 * 1024;

// smoelius: TryDebug, etc. use Nikolai Vazquez's trick from `impls`.
// https://github.com/nvzqz/impls#how-it-works

Expand Down Expand Up @@ -160,33 +157,9 @@ pub fn write_concretization<T>(args: &[&str]) {
write_data(&concretizations, data.as_bytes()).unwrap();
}

#[allow(unused_variables)]
pub fn write_args<T: Serialize>(serde_format: SerdeFormat, args: &T) {
pub fn write_args<T: Serialize>(args: &T) {
let corpus = corpus_directory_from_args_type::<T>();
let data = match serde_format {
#[cfg(any(serde_default, feature = "__serde_bincode"))]
SerdeFormat::Bincode => {
use bincode::Options;
// smoelius: From
// https://github.com/bincode-org/bincode/blob/c44b5e364e7084cdbabf9f94b63a3c7f32b8fb68/src/lib.rs#L102-L103 :
// /// **Warning:** the default configuration used by [`bincode::serialize`] is not
// /// the same as that used by the `DefaultOptions` struct. ...
// The point is that `bincode::serialize(..)` and `bincode::options().serialize(..)` use
// different encodings, even though the latter uses "default" options.
bincode::options()
.with_limit(BYTE_LIMIT)
.serialize(args)
.unwrap()
}
#[cfg(feature = "__serde_cbor")]
SerdeFormat::Cbor => serde_cbor::to_vec(args).unwrap(),
#[cfg(feature = "__serde_cbor4ii")]
SerdeFormat::Cbor4ii => {
let mut data = Vec::new();
cbor4ii::serde::to_writer(&mut data, args).unwrap();
data
}
};
let data = serde_format::serialize(args);
write_data(&corpus, &data).unwrap();
}

Expand All @@ -200,22 +173,6 @@ pub fn write_data(dir: &Path, data: &[u8]) -> io::Result<()> {
write(path_buf, data)
}

pub fn read_args<T: DeserializeOwned, R: Read>(serde_format: SerdeFormat, reader: R) -> Option<T> {
match serde_format {
#[cfg(any(serde_default, feature = "__serde_bincode"))]
SerdeFormat::Bincode => {
use bincode::Options;
bincode::options()
.with_limit(BYTE_LIMIT)
.deserialize_from(reader)
.ok()
}
#[cfg(feature = "__serde_cbor")]
SerdeFormat::Cbor => serde_cbor::from_reader(reader).ok(),
#[cfg(feature = "__serde_cbor4ii")]
SerdeFormat::Cbor4ii => {
let reader = std::io::BufReader::new(reader);
cbor4ii::serde::from_reader(reader).ok()
}
}
pub fn read_args<T: DeserializeOwned, R: Read>(reader: R) -> Option<T> {
serde_format::deserialize(reader)
}
6 changes: 0 additions & 6 deletions test-fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,12 @@ auto_concretize = [
]
serde_bincode = [
"internal/__serde_bincode",
"runtime/__serde_bincode",
"test-fuzz-macro/__serde_bincode",
]
serde_cbor = [
"internal/__serde_cbor",
"runtime/__serde_cbor",
"test-fuzz-macro/__serde_cbor",
]
serde_cbor4ii = [
"internal/__serde_cbor4ii",
"runtime/__serde_cbor4ii",
"test-fuzz-macro/__serde_cbor4ii",
]
__persistent = ["afl", "test-fuzz-macro/__persistent"]

Expand Down
Loading

0 comments on commit 163fee8

Please sign in to comment.