json 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of json might be problematic. Click here for more details.

@@ -7,8 +7,9 @@ module JSON
7
7
  class Parser < StringScanner
8
8
  STRING = /" ((?:[^\x0-\x1f"\\] |
9
9
  \\["\\\/bfnrt] |
10
- \\u[0-9a-fA-F]{4})*)
11
- "/x
10
+ \\u[0-9a-fA-F]{4} |
11
+ \\[\x20-\xff])*)
12
+ "/nx
12
13
  INTEGER = /(-?0|-?[1-9]\d*)/
13
14
  FLOAT = /(-?
14
15
  (?:0|[1-9]\d*)
@@ -45,8 +46,20 @@ module JSON
45
46
  UNPARSED = Object.new
46
47
 
47
48
  # Creates a new JSON::Pure::Parser instance for the string _source_.
48
- def initialize(source)
49
+ #
50
+ # It will be configured by the _opts_ hash. _opts_ can have the following
51
+ # keys:
52
+ # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
53
+ # structures. Disable depth checking with :max_nesting => false.
54
+ def initialize(source, opts = {})
49
55
  super
56
+ if !opts.key?(:max_nesting) # defaults to 19
57
+ @max_nesting = 19
58
+ elsif opts[:max_nesting]
59
+ @max_nesting = opts[:max_nesting]
60
+ else
61
+ @max_nesting = 0
62
+ end
50
63
  @create_id = JSON.create_id
51
64
  end
52
65
 
@@ -61,9 +74,11 @@ module JSON
61
74
  case
62
75
  when scan(OBJECT_OPEN)
63
76
  obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
77
+ @current_nesting = 1
64
78
  obj = parse_object
65
79
  when scan(ARRAY_OPEN)
66
80
  obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
81
+ @current_nesting = 1
67
82
  obj = parse_array
68
83
  when skip(IGNORE)
69
84
  ;
@@ -78,7 +93,8 @@ module JSON
78
93
  private
79
94
 
80
95
  # Unescape characters in strings.
81
- UNESCAPE_MAP = {
96
+ UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
97
+ UNESCAPE_MAP.update({
82
98
  ?" => '"',
83
99
  ?\\ => '\\',
84
100
  ?/ => '/',
@@ -87,12 +103,13 @@ module JSON
87
103
  ?n => "\n",
88
104
  ?r => "\r",
89
105
  ?t => "\t",
90
- }
106
+ ?u => nil,
107
+ })
91
108
 
92
109
  def parse_string
93
110
  if scan(STRING)
94
111
  return '' if self[1].empty?
95
- self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+))) do |c|
112
+ self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
96
113
  if u = UNESCAPE_MAP[c[1]]
97
114
  u
98
115
  else # \uXXXX
@@ -127,15 +144,23 @@ module JSON
127
144
  when (string = parse_string) != UNPARSED
128
145
  string
129
146
  when scan(ARRAY_OPEN)
130
- parse_array
147
+ @current_nesting += 1
148
+ ary = parse_array
149
+ @current_nesting -= 1
150
+ ary
131
151
  when scan(OBJECT_OPEN)
132
- parse_object
152
+ @current_nesting += 1
153
+ obj = parse_object
154
+ @current_nesting -= 1
155
+ obj
133
156
  else
134
157
  UNPARSED
135
158
  end
136
159
  end
137
160
 
138
161
  def parse_array
162
+ raise NestingError, "nesting of #@current_nesting is to deep" if
163
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
139
164
  result = []
140
165
  delim = false
141
166
  until eos?
@@ -166,6 +191,8 @@ module JSON
166
191
  end
167
192
 
168
193
  def parse_object
194
+ raise NestingError, "nesting of #@current_nesting is to deep" if
195
+ @max_nesting.nonzero? && @current_nesting > @max_nesting
169
196
  result = {}
170
197
  delim = false
171
198
  until eos?
@@ -1,6 +1,6 @@
1
1
  module JSON
2
2
  # JSON version
3
- VERSION = '1.0.4'
3
+ VERSION = '1.1.0'
4
4
  VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
@@ -213,6 +213,10 @@ EOT
213
213
  data = JSON.parse(json)
214
214
  assert_equal ['"'], data
215
215
  assert_equal json, JSON.unparse(data)
216
+ json = '["\\\'"]'
217
+ data = JSON.parse(json)
218
+ assert_equal ["'"], data
219
+ assert_equal '["\'"]', JSON.unparse(data)
216
220
  end
217
221
 
218
222
  def test_wrong_inputs
@@ -232,5 +236,20 @@ EOT
232
236
  assert_raises(ParserError) { JSON.parse('[1.]') }
233
237
  assert_raises(ParserError) { JSON.parse(' ') }
234
238
  end
239
+
240
+ def test_nesting
241
+ to_deep = '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]'
242
+ assert_raises(JSON::NestingError) { JSON.parse to_deep }
243
+ assert_raises(JSON::NestingError) { JSON.parser.new(to_deep).parse }
244
+ assert_raises(JSON::NestingError) { JSON.parse to_deep, :max_nesting => 19 }
245
+ ok = JSON.parse to_deep, :max_nesting => 20
246
+ assert_kind_of Array, ok
247
+ ok = JSON.parse to_deep, :max_nesting => nil
248
+ assert_kind_of Array, ok
249
+ ok = JSON.parse to_deep, :max_nesting => false
250
+ assert_kind_of Array, ok
251
+ ok = JSON.parse to_deep, :max_nesting => 0
252
+ assert_kind_of Array, ok
253
+ end
235
254
  end
236
255
  # vim: set et sw=2 ts=2:
@@ -21,7 +21,7 @@ class TC_JSONFixtures < Test::Unit::TestCase
21
21
 
22
22
  def test_failing
23
23
  for (name, source) in @failed
24
- assert_raises(JSON::ParserError,
24
+ assert_raises(JSON::ParserError, JSON::NestingError,
25
25
  "Did not fail for fixture '#{name}'") do
26
26
  JSON.parse(source)
27
27
  end
@@ -116,7 +116,7 @@ loop do
116
116
  puts json.size
117
117
  end
118
118
  begin
119
- o2 = JSON.parse(json)
119
+ o2 = JSON.parse(json, :max_nesting => false)
120
120
  rescue JSON::ParserError => e
121
121
  puts "Caught #{e.class}: #{e.message}\n#{e.backtrace * "\n"}"
122
122
  puts "o1 = #{o1.inspect}", "json = #{json}", "json_str = #{json.inspect}"
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: json
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.4
7
- date: 2007-05-10 00:00:00 +02:00
6
+ version: 1.1.0
7
+ date: 2007-06-04 00:00:00 +02:00
8
8
  summary: A JSON implementation as a Ruby extension
9
9
  require_paths:
10
10
  - ext/json/ext
@@ -34,6 +34,7 @@ files:
34
34
  - VERSION
35
35
  - TODO
36
36
  - tests
37
+ - RUBY
37
38
  - GPL
38
39
  - install.rb
39
40
  - ext
@@ -55,12 +56,11 @@ files:
55
56
  - tests/test_json_generate.rb
56
57
  - tests/test_json_addition.rb
57
58
  - tests/fixtures/fail27.json
59
+ - tests/fixtures/pass26.json
58
60
  - tests/fixtures/fail22.json
59
- - tests/fixtures/fail26.json
60
- - tests/fixtures/fail16.json
61
+ - tests/fixtures/pass17.json
61
62
  - tests/fixtures/fail28.json
62
63
  - tests/fixtures/fail25.json
63
- - tests/fixtures/pass18.json
64
64
  - tests/fixtures/fail9.json
65
65
  - tests/fixtures/fail20.json
66
66
  - tests/fixtures/fail24.json
@@ -68,6 +68,8 @@ files:
68
68
  - tests/fixtures/fail4.json
69
69
  - tests/fixtures/fail7.json
70
70
  - tests/fixtures/fail10.json
71
+ - tests/fixtures/pass15.json
72
+ - tests/fixtures/fail18.json
71
73
  - tests/fixtures/fail13.json
72
74
  - tests/fixtures/fail6.json
73
75
  - tests/fixtures/fail21.json
@@ -78,11 +80,10 @@ files:
78
80
  - tests/fixtures/fail5.json
79
81
  - tests/fixtures/pass1.json
80
82
  - tests/fixtures/fail12.json
81
- - tests/fixtures/fail15.json
82
83
  - tests/fixtures/pass3.json
83
84
  - tests/fixtures/fail8.json
84
- - tests/fixtures/fail17.json
85
85
  - tests/fixtures/fail19.json
86
+ - tests/fixtures/pass16.json
86
87
  - tests/fixtures/pass2.json
87
88
  - tests/fixtures/fail2.json
88
89
  - ext/json