• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![no_main]
2 #![allow(missing_docs)]
3 
4 use android_logger::{AndroidLogger, Config, Filter, FilterBuilder, LogId};
5 use libfuzzer_sys::arbitrary::Arbitrary;
6 use libfuzzer_sys::fuzz_target;
7 use log::{Level, LevelFilter, Log, Record};
8 use std::ffi::CString;
9 
10 // TODO: Remove once Level and LevelInput Arbitrary derivations are upstreamed.
11 // https://github.com/rust-lang/log/issues/530
12 #[derive(Arbitrary, Copy, Clone, Debug)]
13 pub enum LevelInput {
14     Error,
15     Warn,
16     Info,
17     Debug,
18     Trace,
19 }
20 
21 impl From<LevelInput> for Level {
from(l: LevelInput) -> Level22     fn from(l: LevelInput) -> Level {
23         match l {
24             LevelInput::Error => Level::Error,
25             LevelInput::Warn => Level::Warn,
26             LevelInput::Info => Level::Info,
27             LevelInput::Debug => Level::Debug,
28             LevelInput::Trace => Level::Trace,
29         }
30     }
31 }
32 
33 #[derive(Arbitrary, Debug)]
34 pub enum LevelFilterInput {
35     Off,
36     Error,
37     Warn,
38     Info,
39     Debug,
40     Trace,
41 }
42 
43 impl From<&LevelFilterInput> for LevelFilter {
from(l: &LevelFilterInput) -> LevelFilter44     fn from(l: &LevelFilterInput) -> LevelFilter {
45         match l {
46             LevelFilterInput::Off => LevelFilter::Off,
47             LevelFilterInput::Error => LevelFilter::Error,
48             LevelFilterInput::Warn => LevelFilter::Warn,
49             LevelFilterInput::Info => LevelFilter::Info,
50             LevelFilterInput::Debug => LevelFilter::Debug,
51             LevelFilterInput::Trace => LevelFilter::Trace,
52         }
53     }
54 }
55 
56 #[derive(Arbitrary, Copy, Clone, Debug)]
57 pub enum LogIdInput {
58     Main,
59     Radio,
60     Events,
61     System,
62     Crash,
63 }
64 
65 impl From<LogIdInput> for LogId {
from(l: LogIdInput) -> LogId66     fn from(l: LogIdInput) -> LogId {
67         match l {
68             LogIdInput::Main => LogId::Main,
69             LogIdInput::Radio => LogId::Radio,
70             LogIdInput::Events => LogId::Events,
71             LogIdInput::System => LogId::System,
72             LogIdInput::Crash => LogId::Crash,
73         }
74     }
75 }
76 
77 #[derive(Arbitrary, Debug)]
78 struct ConfigInput {
79     log_level: LevelInput,
80     log_id: LogIdInput,
81     filters: Vec<(Option<String>, LevelFilterInput)>,
82     tag: CString,
83 }
84 
85 impl ConfigInput {
get_filter(&self) -> Filter86     fn get_filter(&self) -> Filter {
87         let mut builder = FilterBuilder::new();
88         for (name, level) in &self.filters {
89             builder.filter(name.as_deref(), level.into());
90         }
91         builder.build()
92     }
93 }
94 
95 impl From<ConfigInput> for Config {
from(config_input: ConfigInput) -> Config96     fn from(config_input: ConfigInput) -> Config {
97         Config::default()
98             .with_filter(config_input.get_filter())
99             .with_min_level(config_input.log_level.into())
100             .with_tag(config_input.tag)
101             .with_log_id(config_input.log_id.into())
102     }
103 }
104 
105 #[derive(Arbitrary, Debug)]
106 struct RecordInput {
107     log_level: LevelInput,
108     target: String,
109     module_path: Option<String>,
110     file: Option<String>,
111     line: Option<u32>,
112     message: String,
113 }
114 
115 #[derive(Arbitrary, Debug)]
116 struct LoggerInput {
117     config_input: ConfigInput,
118     record_input: RecordInput,
119 }
120 
121 fuzz_target!(|logger_input: LoggerInput| {
122     let config: Config = logger_input.config_input.into();
123     let logger = AndroidLogger::new(config);
124     let record_input = &logger_input.record_input;
125     logger.log(
126         &Record::builder()
127             .args(format_args!("{}", record_input.message))
128             .level(record_input.log_level.into())
129             .target(&record_input.target)
130             .file(record_input.file.as_deref())
131             .line(record_input.line)
132             .module_path(record_input.module_path.as_deref())
133             .build(),
134     );
135 });
136