Skip to content

Commit df84a47

Browse files
Earlopainnobu
authored andcommitted
Add conversion to the ruby escape implementation
Like `StringValue` in C. When passing `nil` they currently raise `NoMethodError` since it tries to use it as is.
1 parent 05ece45 commit df84a47

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

lib/cgi/escape.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module CGI::Escape
1818
# url_encoded_string = CGI.escape("'Stop!' said Fred")
1919
# # => "%27Stop%21%27+said+Fred"
2020
def escape(string)
21+
string = string_value(string)
2122
encoding = string.encoding
2223
buffer = string.b
2324
buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
@@ -31,6 +32,7 @@ def escape(string)
3132
# string = CGI.unescape("%27Stop%21%27+said+Fred")
3233
# # => "'Stop!' said Fred"
3334
def unescape(string, encoding = @@accept_charset)
35+
string = string_value(string)
3436
str = string.tr('+', ' ')
3537
str = str.b
3638
str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
@@ -45,6 +47,7 @@ def unescape(string, encoding = @@accept_charset)
4547
# url_encoded_string = CGI.escapeURIComponent("'Stop!' said Fred")
4648
# # => "%27Stop%21%27%20said%20Fred"
4749
def escapeURIComponent(string)
50+
string = string_value(string)
4851
encoding = string.encoding
4952
buffer = string.b
5053
buffer.gsub!(/([^a-zA-Z0-9_.\-~]+)/) do |m|
@@ -58,6 +61,7 @@ def escapeURIComponent(string)
5861
# string = CGI.unescapeURIComponent("%27Stop%21%27+said%20Fred")
5962
# # => "'Stop!'+said Fred"
6063
def unescapeURIComponent(string, encoding = @@accept_charset)
64+
string = string_value(string)
6165
str = string.b
6266
str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
6367
[m.delete('%')].pack('H*')
@@ -81,6 +85,7 @@ def unescapeURIComponent(string, encoding = @@accept_charset)
8185
# CGI.escapeHTML('Usage: foo "bar" <baz>')
8286
# # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
8387
def escapeHTML(string)
88+
string = string_value(string)
8489
enc = string.encoding
8590
unless enc.ascii_compatible?
8691
if enc.dummy?
@@ -103,6 +108,7 @@ def escapeHTML(string)
103108
# CGI.unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
104109
# # => "Usage: foo \"bar\" <baz>"
105110
def unescapeHTML(string)
111+
string = string_value(string)
106112
enc = string.encoding
107113
unless enc.ascii_compatible?
108114
if enc.dummy?
@@ -224,4 +230,10 @@ def unescapeElement(string, *elements)
224230
# Synonym for CGI.unescapeElement(str)
225231
alias unescape_element unescapeElement
226232

233+
private
234+
235+
# Like StringValue in C
236+
def string_value(input) # :nodoc:
237+
String.try_convert(input) || raise(TypeError, "no implicit conversion of #{input.class} into String")
238+
end
227239
end

test/cgi/test_cgi_escape.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ def test_cgi_escape_preserve_encoding
4444
assert_equal(Encoding::UTF_8, CGI.escape("\xC0\<\<".dup.force_encoding("UTF-8")).encoding)
4545
end
4646

47+
def test_cgi_escape_nil
48+
assert_raise(TypeError) { CGI.escape(nil) }
49+
end
50+
51+
def test_cgi_escape_conversion
52+
obj = Object.new
53+
def obj.to_str = "foo"
54+
assert_equal("foo", CGI.escape(obj))
55+
end
56+
4757
def test_cgi_unescape
4858
str = CGI.unescape('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93')
4959
assert_equal(@str1, str)
@@ -69,6 +79,10 @@ def test_cgi_unescape_accept_charset
6979
end;
7080
end
7181

82+
def test_cgi_unescape_nil
83+
assert_raise(TypeError) { CGI.unescape(nil) }
84+
end
85+
7286
def test_cgi_escapeURIComponent
7387
assert_equal('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93', CGI.escapeURIComponent(@str1))
7488
assert_equal('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93'.ascii_only?, CGI.escapeURIComponent(@str1).ascii_only?) if defined?(::Encoding)
@@ -94,6 +108,10 @@ def test_cgi_escapeURIComponent_preserve_encoding
94108
assert_equal(Encoding::UTF_8, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("UTF-8")).encoding)
95109
end
96110

111+
def test_cgi_escapeURIComponent_nil
112+
assert_raise(TypeError) { CGI.escapeURIComponent(nil) }
113+
end
114+
97115
def test_cgi_unescapeURIComponent
98116
str = CGI.unescapeURIComponent('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93')
99117
assert_equal(@str1, str)
@@ -126,6 +144,10 @@ def test_cgi_unescapeURIComponent_accept_charset
126144
end;
127145
end
128146

147+
def test_cgi_unescapeURIComponent_nil
148+
assert_raise(TypeError) { CGI.unescapeURIComponent(nil) }
149+
end
150+
129151
def test_cgi_escapeHTML
130152
assert_equal("&#39;&amp;&quot;&gt;&lt;", CGI.escapeHTML("'&\"><"))
131153
end
@@ -155,6 +177,10 @@ def test_cgi_escape_html_dont_freeze
155177
assert_not_predicate CGI.escapeHTML("Ruby".freeze), :frozen?
156178
end
157179

180+
def test_cgi_escape_html_nil
181+
assert_raise(TypeError) { CGI.escapeHTML(nil) }
182+
end
183+
158184
def test_cgi_escape_html_large
159185
return if RUBY_ENGINE == 'jruby'
160186
ulong_max, size_max = RbConfig::LIMITS.values_at("ULONG_MAX", "SIZE_MAX")
@@ -246,6 +272,10 @@ def test_cgi_unescapeHTML_charref_preserve_encoding
246272
assert_equal(enc, result.encoding, name)
247273
end
248274
end
275+
276+
def test_cgi_unescapeHTML_nil
277+
assert_raise(TypeError) { CGI.unescapeHTML(nil) }
278+
end
249279
end
250280

251281
include UnescapeHTMLTests

0 commit comments

Comments
 (0)