aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario Caropreso <mario.caropreso@gmail.com>2013-05-09 13:41:56 +0100
committerMario Caropreso <mario.caropreso@gmail.com>2013-05-09 13:41:56 +0100
commit582b44175b627e3578fe71e1d452c429022da636 (patch)
tree427affdfc7b0836eef4c5b5bc175f8dbfad2c967
parentcecef59fa2f670bbd5b61fcaf54bceae2c4628b0 (diff)
downloadrails-582b44175b627e3578fe71e1d452c429022da636.tar.gz
rails-582b44175b627e3578fe71e1d452c429022da636.tar.bz2
rails-582b44175b627e3578fe71e1d452c429022da636.zip
Added escaping of U+2028 and U+2029 inside the json encoder.
U+2028 and U+2029 are allowed inside strings in JSON (as all literal Unicode characters) but JavaScript defines them as newline seperators. Because no literal newlines are allowed in a string, this causes a ParseError in the browser. We work around this issue by replacing them with the escaped version. The resulting JSON is still valid and can be parsed in the browser. This commit has been coauthored with Viktor Kelemen @yikulju
-rw-r--r--activesupport/CHANGELOG.md6
-rw-r--r--activesupport/lib/active_support/json/encoding.rb9
-rw-r--r--activesupport/test/json/encoding_test.rb4
3 files changed, 14 insertions, 5 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 2e04b17e78..27d4d54afa 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,9 @@
+* Added escaping of U+2028 and U+2029 inside the json encoder.
+ These characters are legal in JSON but break the Javascript interpreter.
+ After escaping them, the JSON is still legal and can be parsed by Javascript.
+
+ *Mario Caropreso*
+
* Fix skipping object callbacks using metadata fetched via callback chain
inspection methods (`_*_callbacks`)
diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
index 9bf1ea35b3..db05b09a66 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -104,7 +104,10 @@ module ActiveSupport
'\\' => '\\\\',
'>' => '\u003E',
'<' => '\u003C',
- '&' => '\u0026' }
+ '&' => '\u0026',
+ "#{0xe2.chr}#{0x80.chr}#{0xa8.chr}" => '\u2028',
+ "#{0xe2.chr}#{0x80.chr}#{0xa9.chr}" => '\u2029',
+ }
class << self
# If true, use ISO 8601 format for dates and times. Otherwise, fall back
@@ -121,9 +124,9 @@ module ActiveSupport
def escape_html_entities_in_json=(value)
self.escape_regex = \
if @escape_html_entities_in_json = value
- /[\x00-\x1F"\\><&]/
+ /[\x00-\x1F"\\><&]|#{0xe2.chr}#{0x80.chr}#{0xa8.chr}|#{0xe2.chr}#{0x80.chr}#{0xa9.chr}/
else
- /[\x00-\x1F"\\]/
+ /[\x00-\x1F"\\]|#{0xe2.chr}#{0x80.chr}#{0xa8.chr}|#{0xe2.chr}#{0x80.chr}#{0xa9.chr}/
end
end
diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
index 8686dcf929..106a7fb522 100644
--- a/activesupport/test/json/encoding_test.rb
+++ b/activesupport/test/json/encoding_test.rb
@@ -45,8 +45,8 @@ class TestJSONEncoding < ActiveSupport::TestCase
StringTests = [[ 'this is the <string>', %("this is the \\u003Cstring\\u003E")],
[ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ],
[ 'http://test.host/posts/1', %("http://test.host/posts/1")],
- [ "Control characters: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- %("Control characters: \\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000B\\f\\r\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F") ]]
+ [ "Control characters: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\342\200\250\342\200\251",
+ %("Control characters: \\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000B\\f\\r\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F\\u2028\\u2029") ]]
ArrayTests = [[ ['a', 'b', 'c'], %([\"a\",\"b\",\"c\"]) ],
[ [1, 'a', :b, nil, false], %([1,\"a\",\"b\",null,false]) ]]