-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
- Correctly error on control characters inside strings - Prevent stack overflow for too nested structures - Minor parsing fixes
- v0.24.1
- 1.15.1
- 1.15.0
- 1.14.1
- 1.14.0
- 1.13.3
- 1.13.2
- 1.13.1
- 1.13.0
- 1.12.2
- 1.12.1
- 1.12.0
- 1.11.2
- 1.11.1
- 1.11.0
- 1.10.1
- 1.10.0
- 1.9.2
- 1.9.1
- 1.9.0
- 1.8.2
- 1.8.1
- 1.8.0
- 1.7.3
- 1.7.2
- 1.7.1
- 1.7.0
- 1.6.2
- 1.6.1
- 1.6.0
- 1.5.1
- 1.5.0
- 1.4.1
- 1.4.0
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.1
- 1.1.0
- 1.0.0
- 0.36.1
- 0.36.0
- 0.35.1
- 0.35.0
- 0.34.0
- 0.33.0
- 0.32.1
- 0.32.0
- 0.31.1
- 0.31.0
- 0.30.1
- 0.30.0
- 0.29.0
- 0.28.0
- 0.27.2
- 0.27.1
- 0.27.0
- 0.26.1
- 0.26.0
- 0.25.1
- 0.25.0
- 0.24.2
- 0.24.1
- 0.24.0
- 0.23.1
- 0.23.0
- 0.22.0
- 0.21.1
- 0.21.0
- 0.20.5
- 0.20.4
- 0.20.3
- 0.20.2
- 0.20.1
- 0.20.0
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
require "./lexer" | ||
|
||
class JSON::Parser | ||
property max_nesting = 512 | ||
|
||
def initialize(string_or_io : String | IO) | ||
@lexer = JSON::Lexer.new(string_or_io) | ||
@nest = 0 | ||
next_token | ||
end | ||
|
||
|
@@ -40,16 +43,20 @@ class JSON::Parser | |
|
||
ary = [] of Type | ||
|
||
if token.type != :"]" | ||
while true | ||
ary << parse_value | ||
|
||
case token.type | ||
when :"," | ||
next_token | ||
unexpected_token if token.type == :"]" | ||
when :"]" | ||
break | ||
nest do | ||
if token.type != :"]" | ||
while true | ||
ary << parse_value | ||
|
||
case token.type | ||
when :"," | ||
next_token | ||
unexpected_token if token.type == :"]" | ||
when :"]" | ||
break | ||
else | ||
unexpected_token | ||
end | ||
end | ||
end | ||
end | ||
|
@@ -64,26 +71,30 @@ class JSON::Parser | |
|
||
object = {} of String => Type | ||
|
||
if token.type != :"}" | ||
while true | ||
check :STRING | ||
key = token.string_value | ||
nest do | ||
if token.type != :"}" | ||
while true | ||
check :STRING | ||
key = token.string_value | ||
|
||
next_token | ||
next_token | ||
|
||
check :":" | ||
next_token | ||
check :":" | ||
next_token | ||
|
||
value = parse_value | ||
value = parse_value | ||
|
||
object[key] = value | ||
object[key] = value | ||
|
||
case token.type | ||
when :"," | ||
next_token_expect_object_key | ||
unexpected_token if token.type == :"}" | ||
when :"}" | ||
break | ||
case token.type | ||
when :"," | ||
next_token_expect_object_key | ||
unexpected_token if token.type == :"}" | ||
when :"}" | ||
break | ||
else | ||
unexpected_token | ||
end | ||
end | ||
end | ||
end | ||
|
@@ -107,6 +118,20 @@ class JSON::Parser | |
end | ||
|
||
private def unexpected_token | ||
raise ParseException.new("unexpected token '#{token}'", token.line_number, token.column_number) | ||
parse_exception "unexpected token '#{token}'" | ||
end | ||
|
||
private def parse_exception(msg) | ||
raise ParseException.new(msg, token.line_number, token.column_number) | ||
end | ||
|
||
private def nest | ||
@nest += 1 | ||
if @nest > @max_nesting | ||
parse_exception "nesting of 101 is too deep" | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
asterite
Member
|
||
end | ||
|
||
yield | ||
@nest -= 1 | ||
end | ||
end |
3 comments
on commit 7eb738f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw that article and thought, "oh here is something I can do real quick", but of course you fixed this 5 hours ago 😂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@will Oops, sorry! I was really curious to see how Crystal performed and it was failing a few cases so I decided to fix them. One of them was stack overflowing by sending a large "[[[[...", for which a fast fix was worth it :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, I read this exact same article on Reddit around 15 minutes before you committed this.
should it be
"nesting of #{@nest} is too deep"
?