Skip to content

Commit a708aae

Browse files
committed
add strict mode to the parser
this mode rejects unknown display hints use strict mode when parsing strings used in the write! and logging macros do not use the strict mode when decoding defmt data in e.g. probe-run
1 parent f946e2f commit a708aae

7 files changed

Lines changed: 39 additions & 8 deletions

File tree

decoder/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ impl<'t, 'b> Decoder<'t, 'b> {
682682
/// Decodes arguments from the stream, according to `format`.
683683
fn decode_format(&mut self, format: &str) -> Result<Vec<Arg<'t>>, DecodeError> {
684684
let mut args = vec![]; // will contain the deserialized arguments on return
685-
let mut params = defmt_parser::parse(format)
685+
let mut params = defmt_parser::parse(format, false)
686686
.map_err(|_| DecodeError::Malformed)?
687687
.iter()
688688
.filter_map(|frag| match frag {
@@ -993,7 +993,7 @@ fn format_args_real(
993993
Ok(())
994994
}
995995

996-
let params = defmt_parser::parse(format).unwrap();
996+
let params = defmt_parser::parse(format, false).unwrap();
997997
let mut buf = String::new();
998998
for param in params {
999999
match param {

macros/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ fn log_ts(level: Level, ts: TokenStream) -> TokenStream {
494494

495495
fn log(level: Level, log: FormatArgs) -> TokenStream2 {
496496
let ls = log.litstr.value();
497-
let fragments = match defmt_parser::parse(&ls) {
497+
let fragments = match defmt_parser::parse(&ls, true) {
498498
Ok(args) => args,
499499
Err(e) => return parse::Error::new(log.litstr.span(), e).to_compile_error(),
500500
};
@@ -989,7 +989,7 @@ pub fn internp(ts: TokenStream) -> TokenStream {
989989
pub fn write(ts: TokenStream) -> TokenStream {
990990
let write = parse_macro_input!(ts as Write);
991991
let ls = write.litstr.value();
992-
let fragments = match defmt_parser::parse(&ls) {
992+
let fragments = match defmt_parser::parse(&ls, true) {
993993
Ok(args) => args,
994994
Err(e) => {
995995
return parse::Error::new(write.litstr.span(), e)

parser/src/lib.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ fn parse_array(mut s: &str) -> Result<usize, Cow<'static, str>> {
153153
}
154154

155155
// example input: "0=Type:hint" (note: no braces)
156-
fn parse_param(mut s: &str) -> Result<Param, Cow<'static, str>> {
156+
fn parse_param(mut s: &str, strict: bool) -> Result<Param, Cow<'static, str>> {
157157
const TYPE_PREFIX: &str = "=";
158158
const HINT_PREFIX: &str = ":";
159159

@@ -249,7 +249,13 @@ fn parse_param(mut s: &str) -> Result<Param, Cow<'static, str>> {
249249
},
250250
"X" => DisplayHint::Hexadecimal { is_uppercase: true },
251251
"?" => DisplayHint::Debug,
252-
_ => DisplayHint::Unknown(s.to_owned()),
252+
_ => {
253+
if strict {
254+
return Err(format!("unknown display hint: {:?}", s).into());
255+
} else {
256+
DisplayHint::Unknown(s.to_owned())
257+
}
258+
}
253259
});
254260
} else if !s.is_empty() {
255261
return Err(format!("unexpected content {:?} in format string", s).into());
@@ -325,7 +331,10 @@ where
325331
}
326332
}
327333

328-
pub fn parse<'f>(format_string: &'f str) -> Result<Vec<Fragment<'f>>, Cow<'static, str>> {
334+
pub fn parse<'f>(
335+
format_string: &'f str,
336+
strict: bool,
337+
) -> Result<Vec<Fragment<'f>>, Cow<'static, str>> {
329338
let mut fragments = Vec::new();
330339

331340
// Index after the `}` of the last format specifier.
@@ -363,7 +372,7 @@ pub fn parse<'f>(format_string: &'f str) -> Result<Vec<Fragment<'f>>, Cow<'stati
363372

364373
// Parse the contents inside the braces.
365374
let param_str = &format_string[brace_pos + 1..][..len];
366-
let param = parse_param(param_str)?;
375+
let param = parse_param(param_str, strict)?;
367376
fragments.push(Fragment::Parameter(Parameter {
368377
index: param.index.unwrap_or_else(|| {
369378
// If there is no explicit index, assign the next one.

tests/ui/log-invalid-hint.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
defmt::info!("{=u8:dunno}", 42)
3+
}

tests/ui/log-invalid-hint.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
error: unknown display hint: "dunno"
2+
--> $DIR/log-invalid-hint.rs:2:18
3+
|
4+
2 | defmt::info!("{=u8:dunno}", 42)
5+
| ^^^^^^^^^^^^^

tests/ui/write-invalid-hint.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
struct S;
2+
3+
impl defmt::Format for S {
4+
fn format(&self, f: defmt::Formatter) {
5+
defmt::write!(f, "{=u8:dunno}", 42)
6+
}
7+
}
8+
9+
fn main() {}

tests/ui/write-invalid-hint.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
error: unknown display hint: "dunno"
2+
--> $DIR/write-invalid-hint.rs:5:26
3+
|
4+
5 | defmt::write!(f, "{=u8:dunno}", 42)
5+
| ^^^^^^^^^^^^^

0 commit comments

Comments
 (0)