blob: 2509ba96eb8f0fc01b7f9ed2ad2525e927880d7c [file] [log] [blame]
#![no_main]
#![allow(missing_docs)]
use android_logger::{AndroidLogger, Config, Filter, FilterBuilder, LogId};
use libfuzzer_sys::arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;
use log::{Level, LevelFilter, Log, Record};
use std::ffi::CString;
// TODO: Remove once Level and LevelInput Arbitrary derivations are upstreamed.
// https://github.com/rust-lang/log/issues/530
#[derive(Arbitrary, Copy, Clone, Debug)]
pub enum LevelInput {
Error,
Warn,
Info,
Debug,
Trace,
}
impl From<LevelInput> for Level {
fn from(l: LevelInput) -> Level {
match l {
LevelInput::Error => Level::Error,
LevelInput::Warn => Level::Warn,
LevelInput::Info => Level::Info,
LevelInput::Debug => Level::Debug,
LevelInput::Trace => Level::Trace,
}
}
}
impl From<LevelInput> for LevelFilter {
fn from(l: LevelInput) -> LevelFilter {
match l {
LevelInput::Error => LevelFilter::Error,
LevelInput::Warn => LevelFilter::Warn,
LevelInput::Info => LevelFilter::Info,
LevelInput::Debug => LevelFilter::Debug,
LevelInput::Trace => LevelFilter::Trace,
}
}
}
#[derive(Arbitrary, Debug)]
pub enum LevelFilterInput {
Off,
Error,
Warn,
Info,
Debug,
Trace,
}
impl From<&LevelFilterInput> for LevelFilter {
fn from(l: &LevelFilterInput) -> LevelFilter {
match l {
LevelFilterInput::Off => LevelFilter::Off,
LevelFilterInput::Error => LevelFilter::Error,
LevelFilterInput::Warn => LevelFilter::Warn,
LevelFilterInput::Info => LevelFilter::Info,
LevelFilterInput::Debug => LevelFilter::Debug,
LevelFilterInput::Trace => LevelFilter::Trace,
}
}
}
#[derive(Arbitrary, Copy, Clone, Debug)]
pub enum LogIdInput {
Main,
Radio,
Events,
System,
Crash,
}
impl From<LogIdInput> for LogId {
fn from(l: LogIdInput) -> LogId {
match l {
LogIdInput::Main => LogId::Main,
LogIdInput::Radio => LogId::Radio,
LogIdInput::Events => LogId::Events,
LogIdInput::System => LogId::System,
LogIdInput::Crash => LogId::Crash,
}
}
}
#[derive(Arbitrary, Debug)]
struct ConfigInput {
log_level: LevelInput,
log_id: LogIdInput,
filters: Vec<(Option<String>, LevelFilterInput)>,
tag: CString,
}
impl ConfigInput {
fn get_filter(&self) -> Filter {
let mut builder = FilterBuilder::new();
for (name, level) in &self.filters {
builder.filter(name.as_deref(), level.into());
}
builder.build()
}
}
impl From<ConfigInput> for Config {
fn from(config_input: ConfigInput) -> Config {
Config::default()
.with_filter(config_input.get_filter())
.with_max_level(config_input.log_level.into())
.with_tag(config_input.tag)
.with_log_buffer(config_input.log_id.into())
}
}
#[derive(Arbitrary, Debug)]
struct RecordInput {
log_level: LevelInput,
target: String,
module_path: Option<String>,
file: Option<String>,
line: Option<u32>,
message: String,
}
#[derive(Arbitrary, Debug)]
struct LoggerInput {
config_input: ConfigInput,
record_input: RecordInput,
}
fuzz_target!(|logger_input: LoggerInput| {
let config: Config = logger_input.config_input.into();
let logger = AndroidLogger::new(config);
let record_input = &logger_input.record_input;
logger.log(
&Record::builder()
.args(format_args!("{}", record_input.message))
.level(record_input.log_level.into())
.target(&record_input.target)
.file(record_input.file.as_deref())
.line(record_input.line)
.module_path(record_input.module_path.as_deref())
.build(),
);
});