Skip to content

Commit acb8a6a

Browse files
quakepeter-jerry-ye
authored andcommitted
feat: add max_nesting_depth
1 parent b6dc78d commit acb8a6a

File tree

5 files changed

+18
-20
lines changed

5 files changed

+18
-20
lines changed

json/internal_types.mbt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ priv struct ParseContext {
1717
mut offset : Int
1818
input : String
1919
end_offset : Int
20+
max_nesting_depth : Int
2021
mut depth : Int
2122
}
2223

2324
///|
24-
fn ParseContext::make(input : String) -> ParseContext {
25-
{ offset: 0, input, end_offset: input.length(), depth: 0 }
25+
fn ParseContext::make(input : String, max_nesting_depth : Int) -> ParseContext {
26+
{ offset: 0, input, end_offset: input.length(), max_nesting_depth, depth: 0 }
2627
}
2728

2829
///|

json/json_test.mbt

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -527,22 +527,16 @@ test "nested json" {
527527
})
528528
}
529529

530+
///|
530531
test "call stack overflow" {
531532
let depth = 50000
532533
let json_string = StringBuilder::new()
533-
for _ in (0..=depth) {
534+
for _ in 0..=depth {
534535
json_string.write_char('[')
535536
}
536-
for _ in (0..=depth) {
537+
for _ in 0..=depth {
537538
json_string.write_char(']')
538539
}
540+
let _ = @json.parse(json_string.to_string()) catch { _ => null }
539541

540-
println("If the parser is vulnerable, this program will crash with a stack overflow.")
541-
542-
match @json.parse(json_string.to_string()) {
543-
Json::Array(arr) => {
544-
println(arr)
545-
}
546-
_ => fail("Parsing failed unexpectedly")
547-
}
548-
}
542+
}

json/lex_misc.mbt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ fn ParseContext::expect_ascii_char(
9393

9494
///|
9595
test "expect_char" {
96-
let ctx = ParseContext::make("abc")
96+
let ctx = ParseContext::make("abc", 1)
9797
ctx.expect_char('a')
9898
ctx.expect_char('b')
9999
ctx.expect_char('c')
@@ -103,7 +103,7 @@ test "expect_char" {
103103
///|
104104
test "expect_char with surrogate pair" {
105105
// "\uD83D\uDE00" // todo: shall we allow this?
106-
let ctx = ParseContext::make("a\u{1F600}bc\u{1F600}c")
106+
let ctx = ParseContext::make("a\u{1F600}bc\u{1F600}c", 1)
107107
ctx.expect_char('a')
108108
ctx.expect_char((0x1F600).unsafe_to_char())
109109
ctx.expect_char('b')

json/parse.mbt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@ pub fn valid(input : String) -> Bool {
2323
}
2424

2525
///|
26-
pub fn parse(input : String) -> Json raise ParseError {
27-
let ctx = ParseContext::make(input)
26+
pub fn parse(
27+
input : String,
28+
max_nesting_depth? : Int = 1024,
29+
) -> Json raise ParseError {
30+
let ctx = ParseContext::make(input, max_nesting_depth)
2831
let val = ctx.parse_value()
2932
ctx.lex_skip_whitespace()
3033
if ctx.offset >= ctx.end_offset {
@@ -59,7 +62,7 @@ fn ParseContext::parse_value2(
5962

6063
///|
6164
fn ParseContext::parse_object(ctx : ParseContext) -> Json raise ParseError {
62-
if ctx.depth >= 500 {
65+
if ctx.depth >= ctx.max_nesting_depth {
6366
raise DepthLimitExceeded
6467
}
6568
ctx.depth += 1
@@ -87,7 +90,7 @@ fn ParseContext::parse_object(ctx : ParseContext) -> Json raise ParseError {
8790

8891
///|
8992
fn ParseContext::parse_array(ctx : ParseContext) -> Json raise ParseError {
90-
if ctx.depth >= 500 {
93+
if ctx.depth >= ctx.max_nesting_depth {
9194
raise DepthLimitExceeded
9295
}
9396
ctx.depth += 1

json/types.mbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub impl Show for ParseError with output(self, logger) {
5353
..write_object(line)
5454
..write_string(", column ")
5555
..write_object(column)
56-
DepthLimitExceeded => logger.write_string("Depth limit exceeded")
56+
DepthLimitExceeded => logger.write_string("Depth limit exceeded, please increase the max_nesting_depth parameter")
5757
}
5858
}
5959

0 commit comments

Comments
 (0)