Fix JSON encoding/decoding bugs dealing with /'s. Closes #9990 [Rick, theamazingrando]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8026 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
Rick Olson 2007-10-26 03:22:02 +00:00
parent 8b2a6014a2
commit 34c125d774
5 changed files with 25 additions and 19 deletions

@ -1,5 +1,7 @@
*SVN* *SVN*
* Fix JSON encoding/decoding bugs dealing with /'s. Closes #9990 [Rick, theamazingrando]
* Introduce a base class for all test cases used by rails applications. ActiveSupport::TestCase [Koz] * Introduce a base class for all test cases used by rails applications. ActiveSupport::TestCase [Koz]
The intention is to use this to reduce the amount of monkeypatching / overriding that The intention is to use this to reduce the amount of monkeypatching / overriding that

@ -43,7 +43,7 @@ def convert_json_to_yaml(json) #:nodoc:
end end
if marks.empty? if marks.empty?
json json.gsub(/\\\//, '/')
else else
# FIXME: multiple slow enumerations # FIXME: multiple slow enumerations
output = ([0] + marks.map(&:succ)). output = ([0] + marks.map(&:succ)).
@ -51,6 +51,7 @@ def convert_json_to_yaml(json) #:nodoc:
map { |left, right| json[left..right] }. map { |left, right| json[left..right] }.
join(" ") join(" ")
times.each { |i| output[i-1] = ' ' } times.each { |i| output[i-1] = ' ' }
output.gsub!(/\\\//, '/')
output output
end end
end end

@ -3,14 +3,15 @@ module JSON
module Encoding module Encoding
ESCAPED_CHARS = { ESCAPED_CHARS = {
"\010" => '\b', "\010" => '\b',
"\f" => '\f', "\f" => '\f',
"\n" => '\n', "\n" => '\n',
"\r" => '\r', "\r" => '\r',
"\t" => '\t', "\t" => '\t',
'"' => '\"', '"' => '\"',
'\\' => '\\\\', '\\' => '\\\\',
">" => '\076', ">" => '\076',
'<' => '\074' '<' => '\074',
'/' => '\\/'
} }
end end
end end
@ -18,7 +19,7 @@ module Encoding
class String class String
def to_json(options = nil) #:nodoc: def to_json(options = nil) #:nodoc:
'"' + gsub(/[\010\f\n\r\t"\\><]/) { |s| '"' + gsub(/[\010\f\n\r\t"\\><\/]/) { |s|
ActiveSupport::JSON::Encoding::ESCAPED_CHARS[s] ActiveSupport::JSON::Encoding::ESCAPED_CHARS[s]
}.gsub(/([\xC0-\xDF][\x80-\xBF]| }.gsub(/([\xC0-\xDF][\x80-\xBF]|
[\xE0-\xEF][\x80-\xBF]{2}| [\xE0-\xEF][\x80-\xBF]{2}|

@ -2,10 +2,10 @@
class TestJSONDecoding < Test::Unit::TestCase class TestJSONDecoding < Test::Unit::TestCase
TESTS = { TESTS = {
%({"returnTo":{"/categories":"/"}}) => {"returnTo" => {"/categories" => "/"}}, %q({"returnTo":{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
%({returnTo:{"/categories":"/"}}) => {"returnTo" => {"/categories" => "/"}}, %q({returnTo:{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
%({"return\\"To\\":":{"/categories":"/"}}) => {"return\"To\":" => {"/categories" => "/"}}, %q({"return\\"To\\":":{"\/categories":"\/"}}) => {"return\"To\":" => {"/categories" => "/"}},
%({"returnTo":{"/categories":1}}) => {"returnTo" => {"/categories" => 1}}, %q({"returnTo":{"\/categories":1}}) => {"returnTo" => {"/categories" => 1}},
%({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]}, %({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]},
%({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]}, %({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]},
%({a: "'", "b": "5,000"}) => {"a" => "'", "b" => "5,000"}, %({a: "'", "b": "5,000"}) => {"a" => "'", "b" => "5,000"},
@ -23,11 +23,12 @@ class TestJSONDecoding < Test::Unit::TestCase
%("\\"") => "\"", %("\\"") => "\"",
%(null) => nil, %(null) => nil,
%(true) => true, %(true) => true,
%(false) => false %(false) => false,
%q("http:\/\/test.host\/posts\/1") => "http://test.host/posts/1"
} }
def test_json_decoding TESTS.each do |json, expected|
TESTS.each do |json, expected| define_method :"test_json_decoding_#{json}" do
assert_nothing_raised do assert_nothing_raised do
assert_equal expected, ActiveSupport::JSON.decode(json) assert_equal expected, ActiveSupport::JSON.decode(json)
end end

@ -14,7 +14,8 @@ def initialize(a, b)
[ 2.5, %(2.5) ]] [ 2.5, %(2.5) ]]
StringTests = [[ 'this is the <string>', %("this is the \\074string\\076")], StringTests = [[ 'this is the <string>', %("this is the \\074string\\076")],
[ 'a "string" with quotes', %("a \\"string\\" with quotes") ]] [ 'a "string" with quotes', %("a \\"string\\" with quotes") ],
[ 'http://test.host/posts/1', %("http:\\/\\/test.host\\/posts\\/1")]]
ArrayTests = [[ ['a', 'b', 'c'], %([\"a\", \"b\", \"c\"]) ], ArrayTests = [[ ['a', 'b', 'c'], %([\"a\", \"b\", \"c\"]) ],
[ [1, 'a', :b, nil, false], %([1, \"a\", \"b\", null, false]) ]] [ [1, 'a', :b, nil, false], %([1, \"a\", \"b\", null, false]) ]]