Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ cfg-if = "1.0"
serde = { version = "1.0", optional = true, default-features = false }
sval = { version = "=1.0.0-alpha.5", optional = true, default-features = false }
value-bag = { version = "=1.0.0-alpha.9", optional = true, default-features = false }
arbitrary = {version = "1.1.6", optional = true, features = ["derive"]}

[dev-dependencies]
rustversion = "1.0"
Expand Down
49 changes: 49 additions & 0 deletions src/arbitrary_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::{Level, MetadataBuilder, RecordBuilder};
use arbitrary::{Arbitrary, Result, Unstructured};

impl<'a> Arbitrary<'a> for RecordBuilder<'a> {
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
let target = &<&'a str>::arbitrary(u)?;
let path = <&'a str>::arbitrary(u)?;
let file = <&'a str>::arbitrary(u)?;

let mut builder = RecordBuilder::new();

builder
// We can't yet provide an arbitrary fmt::Argument object because
// the output of format_args! must be consumed where it is called.
// It cannot be bound to a variable. See https://github.com/rust-lang/rust/issues/92698#ref-pullrequest-1225460272
// .args(format_args!("{}", logoutput))
.metadata(
MetadataBuilder::new()
.level(Level::arbitrary(u)?)
.target(target)
.build(),
)
.file(Some(file.clone()))
.line(Option::<u32>::arbitrary(u)?)
.module_path(Some(path.clone()));

return Ok(builder);
}
}
#[cfg(test)]
mod tests {
use crate::{logger, RecordBuilder};
use arbitrary::{Arbitrary, Unstructured};

#[derive(Arbitrary, Debug)]
struct LogFuzzerInput<'a> {
builder: RecordBuilder<'a>,
message: String,
}

#[test]
fn arbitrary_record() {
let input: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
let mut buf = Unstructured::new(&input);
let mut arb = LogFuzzerInput::arbitrary(&mut buf).unwrap();

logger().log(&arb.builder.args(format_args!("{}", arb.message)).build());
}
}
10 changes: 10 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,12 @@
#[cfg(all(not(feature = "std"), not(test)))]
extern crate core as std;


#[cfg(feature = "arbitrary")]
mod arbitrary_impl;
#[cfg(feature = "arbitrary")]
extern crate arbitrary;

#[macro_use]
extern crate cfg_if;

Expand Down Expand Up @@ -423,6 +429,7 @@ static LEVEL_PARSE_ERROR: &str =
/// [`LevelFilter`](enum.LevelFilter.html).
#[repr(usize)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Level {
/// The "error" level.
///
Expand Down Expand Up @@ -551,6 +558,7 @@ impl Level {
/// [`max_level()`]: fn.max_level.html
/// [`set_max_level`]: fn.set_max_level.html
#[repr(usize)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum LevelFilter {
/// A level lower than all log levels.
Expand Down Expand Up @@ -725,6 +733,8 @@ pub struct Record<'a> {
key_values: KeyValues<'a>,
}



// This wrapper type is only needed so we can
// `#[derive(Debug)]` on `Record`. It also
// provides a useful `Debug` implementation for
Expand Down