Skip to content

Commit 54f8c05

Browse files
fix: avoid recursion in string parsing
1 parent 666605d commit 54f8c05

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

keyvalues-parser/src/grammars/escaped.pest

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ value = _{ quoted_string | obj | unquoted_string }
1919
obj = { "{" ~ pairs ~ "}" }
2020

2121
quoted_string = ${ "\"" ~ quoted_inner ~ "\"" }
22-
quoted_inner = @{ (!("\"" | "\\") ~ ANY)* ~ (escape ~ quoted_inner)? }
23-
escape = @{ "\\" ~ ("\"" | "\\" | "n" | "r" | "t") }
22+
quoted_inner = @{ char* }
23+
char = {
24+
!("\"" | "\\") ~ ANY
25+
| "\\" ~ ("\"" | "\\" | "n" | "r" | "t")
26+
}
2427

2528
unquoted_string = @{ unquoted_char+ }
2629
// The wiki page just states that an unquoted string ends with ", {, }, or any

keyvalues-parser/tests/regressions/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
1+
use std::iter;
2+
13
use keyvalues_parser::Vdf;
24

35
mod fuzzer;
46

7+
#[test]
8+
fn issue_54() {
9+
// Generates strings e.g. `lots_of_escaped(2)` gives `"" "\"\""`
10+
fn lots_of_escapes(num_escaped: usize) -> String {
11+
iter::once("\"\" \"")
12+
.chain(iter::repeat("\\\"").take(num_escaped))
13+
.chain(iter::once("\""))
14+
.collect()
15+
}
16+
17+
let vdf_text = lots_of_escapes(20_000);
18+
Vdf::parse(&vdf_text).unwrap();
19+
}
20+
521
#[test]
622
fn raw_no_newline() {
723
let vdf_text = "no newline";

0 commit comments

Comments
 (0)