Skip to content
This repository

Escape \u2028 and \u2029 for 1.8 #44

Merged
merged 4 commits into from over 1 year ago

3 participants

Benjamin Manns James Alexander Rosen Konstantin Haase
Benjamin Manns

In 1.8, the string "\u2028" is converted to "u2028", so any JSON containing "u2028" would be replaced with "\\u2028", and any string literals "\u2028" would not get escaped. This patch uses octet literals if the Ruby version is less than 1.9, and Unicode literals if the Ruby version is 1.9 or greater.

If anyone doesn't like the Ruby version comparison within the code, I can remove the comparison and use the octet literal for all versions of Ruby, because 1.9 interprets "\342\200\250" the same as "\u2028".

added some commits September 25, 2011
Benjamin Manns Split "should not allow literal U+2028 or U+2029" assigns and tests f…
…or ">= 1.9" and "< 1.9".
eff0146
Benjamin Manns Use octets in string literals when translating U+2028 and U+2029 if u…
…sing a Ruby version less than 1.9.

Previously, this would translate "u2028" to "\\u2028", because the \u escape character doesn't exist in 1.8.
4122df8
Benjamin Manns Replace Gem::Version comparison with "\u2028" == 'u2028' comparison.
This ensures that the Unicode character is properly translated without relying on Gem::Version. Thanks to @judofyr.
2b3d626
Benjamin Manns Move U+2028 and U+2029 into constants.
This allows the Ruby compatibility check to be run once on startup rather than for every request. Thanks to @judofyr.
75b4ef8
James Alexander Rosen

The tests are a little hard to understand unless you've read the comments on this PR. A comment there or more descriptive naming would help.

+1 otherwise.

Konstantin Haase rkh merged commit 42b92b7 into from December 10, 2012
Konstantin Haase rkh closed this December 10, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 4 unique commits by 1 author.

Sep 25, 2011
Benjamin Manns Split "should not allow literal U+2028 or U+2029" assigns and tests f…
…or ">= 1.9" and "< 1.9".
eff0146
Benjamin Manns Use octets in string literals when translating U+2028 and U+2029 if u…
…sing a Ruby version less than 1.9.

Previously, this would translate "u2028" to "\\u2028", because the \u escape character doesn't exist in 1.8.
4122df8
Sep 26, 2011
Benjamin Manns Replace Gem::Version comparison with "\u2028" == 'u2028' comparison.
This ensures that the Unicode character is properly translated without relying on Gem::Version. Thanks to @judofyr.
2b3d626
Benjamin Manns Move U+2028 and U+2029 into constants.
This allows the Ruby compatibility check to be run once on startup rather than for every request. Thanks to @judofyr.
75b4ef8
This page is out of date. Refresh to see the latest.
14  lib/rack/contrib/jsonp.rb
@@ -10,6 +10,18 @@ class JSONP
10 10
     VALID_JS_VAR    = /[a-zA-Z_$][\w$]*/
11 11
     VALID_CALLBACK  = /\A#{VALID_JS_VAR}(?:\.?#{VALID_JS_VAR})*\z/
12 12
 
  13
+    # These hold the Unicode characters \u2028 and \u2029.
  14
+    #
  15
+    # They are defined in constants for Ruby 1.8 compatibility.
  16
+    #
  17
+    # In 1.8
  18
+    # "\u2028" # => "u2028"
  19
+    # "\u2029" # => "u2029"
  20
+    # In 1.9
  21
+    # "\342\200\250" # => "\u2028"
  22
+    # "\342\200\251" # => "\u2029"
  23
+    U2028, U2029 = ("\u2028" == 'u2028') ? ["\342\200\250", "\342\200\251"] : ["\u2028", "\u2029"]
  24
+
13 25
     def initialize(app)
14 26
       @app = app
15 27
     end
@@ -83,7 +95,7 @@ def pad(callback, response, body = "")
83 95
         # replacing them with the escaped version. This should be safe because
84 96
         # according to the JSON spec, these characters are *only* valid inside
85 97
         # a string and should therefore not be present any other places.
86  
-        body << s.to_s.gsub("\u2028", '\u2028').gsub("\u2029", '\u2029')
  98
+        body << s.to_s.gsub(U2028, '\u2028').gsub(U2029, '\u2029')
87 99
       end
88 100
 
89 101
       ["#{callback}(#{body})"]
12  test/spec_rack_jsonp.rb
@@ -53,12 +53,20 @@
53 53
     end
54 54
 
55 55
     specify "should not allow literal U+2028 or U+2029" do
56  
-      test_body = "{\"bar\":\"\u2028 and \u2029\"}"
  56
+      test_body = unless "\u2028" == 'u2028'
  57
+        "{\"bar\":\"\u2028 and \u2029\"}"
  58
+      else
  59
+        "{\"bar\":\"\342\200\250 and \342\200\251\"}"
  60
+      end
57 61
       callback = 'foo'
58 62
       app = lambda { |env| [200, {'Content-Type' => 'application/json'}, [test_body]] }
59 63
       request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
60 64
       body = Rack::JSONP.new(app).call(request).last
61  
-      body.join.should.not.match(/\u2028|\u2029/)
  65
+      unless "\u2028" == 'u2028'
  66
+        body.join.should.not.match(/\u2028|\u2029/)
  67
+      else
  68
+        body.join.should.not.match(/\342\200\250|\342\200\251/)
  69
+      end
62 70
     end
63 71
     
64 72
     context "but is empty" do
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.