• 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 impl From<LevelInput> for LevelFilter {
from(l: LevelInput) -> LevelFilter34     fn from(l: LevelInput) -> LevelFilter {
35         match l {
36             LevelInput::Error => LevelFilter::Error,
37             LevelInput::Warn => LevelFilter::Warn,
38             LevelInput::Info => LevelFilter::Info,
39             LevelInput::Debug => LevelFilter::Debug,
40             LevelInput::Trace => LevelFilter::Trace,
41         }
42     }
43 }
44 
45 #[derive(Arbitrary, Debug)]
46 pub enum LevelFilterInput {
47     Off,
48     Error,
49     Warn,
50     Info,
51     Debug,
52     Trace,
53 }
54 
55 impl From<&LevelFilterInput> for LevelFilter {
from(l: &LevelFilterInput) -> LevelFilter56     fn from(l: &LevelFilterInput) -> LevelFilter {
57         match l {
58             LevelFilterInput::Off => LevelFilter::Off,
59             LevelFilterInput::Error => LevelFilter::Error,
60             LevelFilterInput::Warn => LevelFilter::Warn,
61             LevelFilterInput::Info => LevelFilter::Info,
62             LevelFilterInput::Debug => LevelFilter::Debug,
63             LevelFilterInput::Trace => LevelFilter::Trace,
64         }
65     }
66 }
67 
68 #[derive(Arbitrary, Copy, Clone, Debug)]
69 pub enum LogIdInput {
70     Main,
71     Radio,
72     Events,
73     System,
74     Crash,
75 }
76 
77 impl From<LogIdInput> for LogId {
from(l: LogIdInput) -> LogId78     fn from(l: LogIdInput) -> LogId {
79         match l {
80             LogIdInput::Main => LogId::Main,
81             LogIdInput::Radio => LogId::Radio,
82             LogIdInput::Events => LogId::Events,
83             LogIdInput::System => LogId::System,
84             LogIdInput::Crash => LogId::Crash,
85         }
86     }
87 }
88 
89 #[derive(Arbitrary, Debug)]
90 struct ConfigInput {
91     log_level: LevelInput,
92     log_id: LogIdInput,
93     filters: Vec<(Option<String>, LevelFilterInput)>,
94     tag: CString,
95 }
96 
97 impl ConfigInput {
get_filter(&self) -> Filter98     fn get_filter(&self) -> Filter {
99         let mut builder = FilterBuilder::new();
100         for (name, level) in &self.filters {
101             builder.filter(name.as_deref(), level.into());
102         }
103         builder.build()
104     }
105 }
106 
107 impl From<ConfigInput> for Config {
from(config_input: ConfigInput) -> Config108     fn from(config_input: ConfigInput) -> Config {
109         Config::default()
110             .with_filter(config_input.get_filter())
111             .with_max_level(config_input.log_level.into())
112             .with_tag(config_input.tag)
113             .with_log_buffer(config_input.log_id.into())
114     }
115 }
116 
117 #[derive(Arbitrary, Debug)]
118 struct RecordInput {
119     log_level: LevelInput,
120     target: String,
121     module_path: Option<String>,
122     file: Option<String>,
123     line: Option<u32>,
124     message: String,
125 }
126 
127 #[derive(Arbitrary, Debug)]
128 struct LoggerInput {
129     config_input: ConfigInput,
130     record_input: RecordInput,
131 }
132 
133 fuzz_target!(|logger_input: LoggerInput| {
134     let config: Config = logger_input.config_input.into();
135     let logger = AndroidLogger::new(config);
136     let record_input = &logger_input.record_input;
137     logger.log(
138         &Record::builder()
139             .args(format_args!("{}", record_input.message))
140             .level(record_input.log_level.into())
141             .target(&record_input.target)
142             .file(record_input.file.as_deref())
143             .line(record_input.line)
144             .module_path(record_input.module_path.as_deref())
145             .build(),
146     );
147 });
148