diff options
Diffstat (limited to 'test/cgi')
| -rw-r--r-- | test/cgi/test_cgi_cookie.rb | 121 | ||||
| -rw-r--r-- | test/cgi/test_cgi_core.rb | 85 | ||||
| -rw-r--r-- | test/cgi/test_cgi_header.rb | 31 | ||||
| -rw-r--r-- | test/cgi/test_cgi_modruby.rb | 11 | ||||
| -rw-r--r-- | test/cgi/test_cgi_multipart.rb | 31 | ||||
| -rw-r--r-- | test/cgi/test_cgi_session.rb | 55 | ||||
| -rw-r--r-- | test/cgi/test_cgi_tag_helper.rb | 16 | ||||
| -rw-r--r-- | test/cgi/test_cgi_util.rb | 257 | ||||
| -rw-r--r-- | test/cgi/update_env.rb | 9 |
9 files changed, 469 insertions, 147 deletions
diff --git a/test/cgi/test_cgi_cookie.rb b/test/cgi/test_cgi_cookie.rb index c1c6a30e70..eadae45313 100644 --- a/test/cgi/test_cgi_cookie.rb +++ b/test/cgi/test_cgi_cookie.rb @@ -1,21 +1,26 @@ +# frozen_string_literal: true require 'test/unit' require 'cgi' require 'stringio' +require_relative 'update_env' class CGICookieTest < Test::Unit::TestCase + include UpdateEnv def setup - ENV['REQUEST_METHOD'] = 'GET' - @str1="\xE3\x82\x86\xE3\x82\x93\xE3\x82\x86\xE3\x82\x93" + @environ = {} + update_env( + 'REQUEST_METHOD' => 'GET', + 'SCRIPT_NAME' => nil, + ) + @str1="\xE3\x82\x86\xE3\x82\x93\xE3\x82\x86\xE3\x82\x93".dup @str1.force_encoding("UTF-8") if defined?(::Encoding) end def teardown - %W[REQUEST_METHOD SCRIPT_NAME].each do |name| - ENV.delete(name) - end + ENV.update(@environ) end @@ -27,20 +32,22 @@ class CGICookieTest < Test::Unit::TestCase assert_nil(cookie.expires) assert_equal('', cookie.path) assert_equal(false, cookie.secure) + assert_equal(false, cookie.httponly) assert_equal("name1=val1&%26%3C%3E%22&%E3%82%86%E3%82%93%E3%82%86%E3%82%93; path=", cookie.to_s) end def test_cgi_cookie_new_complex t = Time.gm(2030, 12, 31, 23, 59, 59) - value = ['val1', '&<>"', "\xA5\xE0\xA5\xB9\xA5\xAB"] + value = ['val1', '&<>"', "\xA5\xE0\xA5\xB9\xA5\xAB".dup] value[2].force_encoding("EUC-JP") if defined?(::Encoding) cookie = CGI::Cookie.new('name'=>'name1', 'value'=>value, 'path'=>'/cgi-bin/myapp/', 'domain'=>'www.example.com', 'expires'=>t, - 'secure'=>true + 'secure'=>true, + 'httponly'=>true ) assert_equal('name1', cookie.name) assert_equal(value, cookie.value) @@ -48,7 +55,29 @@ class CGICookieTest < Test::Unit::TestCase assert_equal(t, cookie.expires) assert_equal('/cgi-bin/myapp/', cookie.path) assert_equal(true, cookie.secure) - assert_equal('name1=val1&%26%3C%3E%22&%A5%E0%A5%B9%A5%AB; domain=www.example.com; path=/cgi-bin/myapp/; expires=Tue, 31 Dec 2030 23:59:59 GMT; secure', cookie.to_s) + assert_equal(true, cookie.httponly) + assert_equal('name1=val1&%26%3C%3E%22&%A5%E0%A5%B9%A5%AB; domain=www.example.com; path=/cgi-bin/myapp/; expires=Tue, 31 Dec 2030 23:59:59 GMT; secure; HttpOnly', cookie.to_s) + end + + + def test_cgi_cookie_new_with_domain + h = {'name'=>'name1', 'value'=>'value1'} + cookie = CGI::Cookie.new(h.merge('domain'=>'a.example.com')) + assert_equal('a.example.com', cookie.domain) + + cookie = CGI::Cookie.new(h.merge('domain'=>'.example.com')) + assert_equal('.example.com', cookie.domain) + + cookie = CGI::Cookie.new(h.merge('domain'=>'1.example.com')) + assert_equal('1.example.com', cookie.domain, 'enhanced by RFC 1123') + + assert_raise(ArgumentError) { + CGI::Cookie.new(h.merge('domain'=>'-a.example.com')) + } + + assert_raise(ArgumentError) { + CGI::Cookie.new(h.merge('domain'=>'a-.example.com')) + } end @@ -80,9 +109,12 @@ class CGICookieTest < Test::Unit::TestCase assert_equal(name, cookie.name) assert_equal(value, cookie.value) end - ## ',' separator - cookie_str = 'name1=val1&val2, name2=val2&%26%3C%3E%22&%E3%82%86%E3%82%93%E3%82%86%E3%82%93,_session_id=12345' + ## don't allow ',' separator + cookie_str = 'name1=val1&val2, name2=val2' cookies = CGI::Cookie.parse(cookie_str) + list = [ + ['name1', ['val1', 'val2, name2=val2']], + ] list.each do |name, value| cookie = cookies[name] assert_equal(name, cookie.name) @@ -90,6 +122,11 @@ class CGICookieTest < Test::Unit::TestCase end end + def test_cgi_cookie_parse_not_decode_name + cookie_str = "%66oo=baz;foo=bar" + cookies = CGI::Cookie.parse(cookie_str) + assert_equal({"%66oo" => ["baz"], "foo" => ["bar"]}, cookies) + end def test_cgi_cookie_arrayinterface cookie = CGI::Cookie.new('name1', 'a', 'b', 'c') @@ -102,6 +139,70 @@ class CGICookieTest < Test::Unit::TestCase end + def test_cgi_cookie_domain_injection_into_name + name = "a=b; domain=example.com;" + path = "/" + domain = "example.jp" + assert_raise(ArgumentError) do + CGI::Cookie.new('name' => name, + 'value' => "value", + 'domain' => domain, + 'path' => path) + end + end + + + def test_cgi_cookie_newline_injection_into_name + name = "a=b;\r\nLocation: http://example.com#" + path = "/" + domain = "example.jp" + assert_raise(ArgumentError) do + CGI::Cookie.new('name' => name, + 'value' => "value", + 'domain' => domain, + 'path' => path) + end + end + + + def test_cgi_cookie_multibyte_injection_into_name + name = "a=b;\u3042" + path = "/" + domain = "example.jp" + assert_raise(ArgumentError) do + CGI::Cookie.new('name' => name, + 'value' => "value", + 'domain' => domain, + 'path' => path) + end + end + + + def test_cgi_cookie_injection_into_path + name = "name" + path = "/; samesite=none" + domain = "example.jp" + assert_raise(ArgumentError) do + CGI::Cookie.new('name' => name, + 'value' => "value", + 'domain' => domain, + 'path' => path) + end + end + + + def test_cgi_cookie_injection_into_domain + name = "name" + path = "/" + domain = "example.jp; samesite=none" + assert_raise(ArgumentError) do + CGI::Cookie.new('name' => name, + 'value' => "value", + 'domain' => domain, + 'path' => path) + end + end + instance_methods.each do |method| private method if method =~ /^test_(.*)/ && $1 != ENV['TEST'] diff --git a/test/cgi/test_cgi_core.rb b/test/cgi/test_cgi_core.rb index 274d088f0f..f7adb7e99f 100644 --- a/test/cgi/test_cgi_core.rb +++ b/test/cgi/test_cgi_core.rb @@ -1,12 +1,15 @@ +# frozen_string_literal: true require 'test/unit' require 'cgi' require 'stringio' +require_relative 'update_env' class CGICoreTest < Test::Unit::TestCase - + include UpdateEnv def setup + @environ = {} #@environ = { # 'SERVER_PROTOCOL' => 'HTTP/1.1', # 'REQUEST_METHOD' => 'GET', @@ -15,35 +18,32 @@ class CGICoreTest < Test::Unit::TestCase #ENV.update(@environ) end - def teardown - @environ.each do |key, val| ENV.delete(key) end + ENV.update(@environ) $stdout = STDOUT end def test_cgi_parse_illegal_query - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', 'QUERY_STRING' => 'a=111&&b=222&c&d=', 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;', 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } - ENV.update(@environ) + ) cgi = CGI.new assert_equal(["a","b","c","d"],cgi.keys.sort) assert_equal("",cgi["d"]) end def test_cgi_core_params_GET - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', 'QUERY_STRING' => 'id=123&id=456&id=&id&str=%40h+%3D%7E+%2F%5E%24%2F', 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;', 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } - ENV.update(@environ) + ) cgi = CGI.new ## cgi[] assert_equal('123', cgi['id']) @@ -68,14 +68,13 @@ class CGICoreTest < Test::Unit::TestCase def test_cgi_core_params_POST query_str = 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F' - @environ = { + update_env( 'REQUEST_METHOD' => 'POST', 'CONTENT_LENGTH' => query_str.length.to_s, 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;', 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } - ENV.update(@environ) + ) $stdin = StringIO.new $stdin << query_str $stdin.rewind @@ -89,17 +88,18 @@ class CGICoreTest < Test::Unit::TestCase ## invalid parameter name assert_equal('', cgi['*notfound*']) assert_equal([], cgi.params['*notfound*']) + ensure + $stdin = STDIN end def test_cgi_core_params_encoding_check query_str = 'str=%BE%BE%B9%BE' - @environ = { + update_env( 'REQUEST_METHOD' => 'POST', 'CONTENT_LENGTH' => query_str.length.to_s, 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } - ENV.update(@environ) + ) $stdin = StringIO.new $stdin << query_str $stdin.rewind @@ -107,11 +107,11 @@ class CGICoreTest < Test::Unit::TestCase hash={} cgi = CGI.new(:accept_charset=>"UTF-8"){|key,val|hash[key]=val} ## cgi[] - assert_equal("\xBE\xBE\xB9\xBE".force_encoding("UTF-8"), cgi['str']) + assert_equal("\xBE\xBE\xB9\xBE".dup.force_encoding("UTF-8"), cgi['str']) ## cgi.params - assert_equal(["\xBE\xBE\xB9\xBE".force_encoding("UTF-8")], cgi.params['str']) + assert_equal(["\xBE\xBE\xB9\xBE".dup.force_encoding("UTF-8")], cgi.params['str']) ## accept-charset error - assert_equal({"str"=>"\xBE\xBE\xB9\xBE".force_encoding("UTF-8")},hash) + assert_equal({"str"=>"\xBE\xBE\xB9\xBE".dup.force_encoding("UTF-8")},hash) $stdin.rewind assert_raise(CGI::InvalidEncoding) do @@ -121,24 +121,25 @@ class CGICoreTest < Test::Unit::TestCase $stdin.rewind cgi = CGI.new(:accept_charset=>"EUC-JP") ## cgi[] - assert_equal("\xBE\xBE\xB9\xBE".force_encoding("EUC-JP"), cgi['str']) + assert_equal("\xBE\xBE\xB9\xBE".dup.force_encoding("EUC-JP"), cgi['str']) ## cgi.params - assert_equal(["\xBE\xBE\xB9\xBE".force_encoding("EUC-JP")], cgi.params['str']) + assert_equal(["\xBE\xBE\xB9\xBE".dup.force_encoding("EUC-JP")], cgi.params['str']) else assert(true) end + ensure + $stdin = STDIN end def test_cgi_core_cookie - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F', 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;', 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } - ENV.update(@environ) + ) cgi = CGI.new assert_not_equal(nil,cgi.cookies) [ ['_session_id', ['12345'], ], @@ -156,11 +157,10 @@ class CGICoreTest < Test::Unit::TestCase def test_cgi_core_maxcontentlength - @environ = { + update_env( 'REQUEST_METHOD' => 'POST', 'CONTENT_LENGTH' => (64 * 1024 * 1024).to_s - } - ENV.update(@environ) + ) ex = assert_raise(StandardError) do CGI.new end @@ -169,14 +169,13 @@ class CGICoreTest < Test::Unit::TestCase def test_cgi_core_out - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F', 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;', 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } - ENV.update(@environ) + ) cgi = CGI.new ## euc string euc_str = "\270\253\244\355\241\242\277\315\244\254\245\264\245\337\244\316\244\350\244\246\244\300" @@ -201,7 +200,7 @@ class CGICoreTest < Test::Unit::TestCase cgi.out(options) { euc_str } assert_equal('en', options['language']) ## HEAD method - ENV['REQUEST_METHOD'] = 'HEAD' + update_env('REQUEST_METHOD' => 'HEAD') options = { 'charset'=>'utf8' } $stdout = StringIO.new cgi.out(options) { euc_str } @@ -214,10 +213,9 @@ class CGICoreTest < Test::Unit::TestCase def test_cgi_core_print - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', - } - ENV.update(@environ) + ) cgi = CGI.new $stdout = StringIO.new str = "foobar" @@ -229,10 +227,9 @@ class CGICoreTest < Test::Unit::TestCase def test_cgi_core_environs - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', - } - ENV.update(@environ) + ) cgi = CGI.new ## list1 = %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO @@ -246,9 +243,8 @@ class CGICoreTest < Test::Unit::TestCase # list2 = %w[ CONTENT_LENGTH SERVER_PORT ] ## string expected list1.each do |name| - @environ[name] = "**#{name}**" + update_env(name => "**#{name}**") end - ENV.update(@environ) list1.each do |name| method = name.sub(/\AHTTP_/, '').downcase actual = cgi.__send__ method @@ -256,23 +252,22 @@ class CGICoreTest < Test::Unit::TestCase assert_equal(expected, actual) end ## integer expected - ENV['CONTENT_LENGTH'] = '123' - ENV['SERVER_PORT'] = '8080' + update_env('CONTENT_LENGTH' => '123') + update_env('SERVER_PORT' => '8080') assert_equal(123, cgi.content_length) assert_equal(8080, cgi.server_port) ## raw cookie - ENV['HTTP_COOKIE'] = 'name1=val1' - ENV['HTTP_COOKIE2'] = 'name2=val2' + update_env('HTTP_COOKIE' => 'name1=val1') + update_env('HTTP_COOKIE2' => 'name2=val2') assert_equal('name1=val1', cgi.raw_cookie) assert_equal('name2=val2', cgi.raw_cookie2) end def test_cgi_core_htmltype_header - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', - } - ENV.update(@environ) + ) ## no htmltype cgi = CGI.new assert_raise(NoMethodError) do cgi.doctype end diff --git a/test/cgi/test_cgi_header.rb b/test/cgi/test_cgi_header.rb index 9022301153..ec2f4deb72 100644 --- a/test/cgi/test_cgi_header.rb +++ b/test/cgi/test_cgi_header.rb @@ -1,23 +1,26 @@ +# frozen_string_literal: true require 'test/unit' require 'cgi' require 'time' +require_relative 'update_env' class CGIHeaderTest < Test::Unit::TestCase + include UpdateEnv def setup - @environ = { + @environ = {} + update_env( 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_METHOD' => 'GET', 'SERVER_SOFTWARE' => 'Apache 2.2.0', - } - ENV.update(@environ) + ) end def teardown - @environ.each do |key, val| ENV.delete(key) end + ENV.update(@environ) end @@ -55,7 +58,7 @@ class CGIHeaderTest < Test::Unit::TestCase 'expires' => Time.gm(2000, 1, 23, 12, 34, 56), 'location' => 'http://www.ruby-lang.org/', } - expected = "Status: 302 Found\r\n" + expected = "Status: 302 Found\r\n".dup expected << "Server: webrick\r\n" expected << "Connection: close\r\n" expected << "Content-Type: text/xhtml; charset=utf8\r\n" @@ -113,7 +116,7 @@ class CGIHeaderTest < Test::Unit::TestCase CGI::Cookie.new('name'=>'name2', 'value'=>'value2', 'secure'=>true), ] cgi.instance_variable_set('@output_cookies', cookies) - expected = "Content-Type: text/html; charset=utf8\r\n" + expected = "Content-Type: text/html; charset=utf8\r\n".dup expected << "Set-Cookie: name1=abc&123; path=\r\n" expected << "Set-Cookie: name2=value2; path=; secure\r\n" expected << "\r\n" @@ -144,11 +147,11 @@ class CGIHeaderTest < Test::Unit::TestCase date = /^Date: ([A-Z][a-z]{2}, \d{2} [A-Z][a-z]{2} \d{4} \d\d:\d\d:\d\d GMT)\r\n/ [actual1, actual2, actual3].each do |actual| assert_match(date, actual) - assert_includes(time_start..time_end, date =~ actual && Time.parse($1).to_i) + assert_include(time_start..time_end, date =~ actual && Time.parse($1).to_i) actual.sub!(date, "Date: DATE_IS_REMOVED\r\n") end ## assertion - expected = "HTTP/1.1 200 OK\r\n" + expected = "HTTP/1.1 200 OK\r\n".dup expected << "Date: DATE_IS_REMOVED\r\n" expected << "Server: Apache 2.2.0\r\n" expected << "Connection: close\r\n" @@ -160,10 +163,10 @@ class CGIHeaderTest < Test::Unit::TestCase expected.sub!(/^HTTP\/1.1 200 OK\r\n/, "HTTP/1.1 302 Found\r\n") expected.sub!(/\r\n\r\n/, "\r\nlocation: http://www.example.com/\r\n\r\n") assert_equal(expected, actual3) - expected = "Content-Type: text/html\r\n" + expected = "Content-Type: text/html\r\n".dup expected << "\r\n" assert_equal(expected, actual4) - expected = "Status: 302 Found\r\n" + expected = "Status: 302 Found\r\n".dup expected << "Content-Type: text/html\r\n" expected << "location: http://www.example.com/\r\n" expected << "\r\n" @@ -173,6 +176,14 @@ class CGIHeaderTest < Test::Unit::TestCase end + def test_cgi_http_header_crlf_injection + cgi = CGI.new + assert_raise(RuntimeError) { cgi.http_header("text/xhtml\r\nBOO") } + assert_raise(RuntimeError) { cgi.http_header("type" => "text/xhtml\r\nBOO") } + assert_raise(RuntimeError) { cgi.http_header("status" => "200 OK\r\nBOO") } + assert_raise(RuntimeError) { cgi.http_header("location" => "text/xhtml\r\nBOO") } + end + instance_methods.each do |method| private method if method =~ /^test_(.*)/ && $1 != ENV['TEST'] diff --git a/test/cgi/test_cgi_modruby.rb b/test/cgi/test_cgi_modruby.rb index b0fc442bc9..90132962b5 100644 --- a/test/cgi/test_cgi_modruby.rb +++ b/test/cgi/test_cgi_modruby.rb @@ -1,17 +1,20 @@ +# frozen_string_literal: true require 'test/unit' require 'cgi' +require_relative 'update_env' class CGIModrubyTest < Test::Unit::TestCase + include UpdateEnv def setup - @environ = { + @environ = {} + update_env( 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_METHOD' => 'GET', #'QUERY_STRING' => 'a=foo&b=bar', - } - ENV.update(@environ) + ) CGI.class_eval { const_set(:MOD_RUBY, true) } Apache._reset() #@cgi = CGI.new @@ -20,7 +23,7 @@ class CGIModrubyTest < Test::Unit::TestCase def teardown - @environ.each do |key, val| ENV.delete(key) end + ENV.update(@environ) CGI.class_eval { remove_const(:MOD_RUBY) } end diff --git a/test/cgi/test_cgi_multipart.rb b/test/cgi/test_cgi_multipart.rb index 1325798e95..5e8ec25390 100644 --- a/test/cgi/test_cgi_multipart.rb +++ b/test/cgi/test_cgi_multipart.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true require 'test/unit' require 'cgi' require 'tempfile' require 'stringio' +require_relative 'update_env' ## @@ -31,7 +33,7 @@ class MultiPart def initialize(boundary=nil) @boundary = boundary || create_boundary() - @buf = '' + @buf = ''.dup @buf.force_encoding(::Encoding::ASCII_8BIT) if defined?(::Encoding) end attr_reader :boundary @@ -44,15 +46,14 @@ class MultiPart buf << "Content-Disposition: form-data: name=\"#{name}\"#{s}\r\n" buf << "Content-Type: #{content_type}\r\n" if content_type buf << "\r\n" - value = value.dup.force_encoding(::Encoding::ASCII_8BIT) if defined?(::Encoding) - buf << value + buf << value.b buf << "\r\n" return self end def close buf = @buf - @buf = '' + @buf = ''.dup return buf << "--#{boundary}--\r\n" end @@ -104,16 +105,21 @@ end class CGIMultipartTest < Test::Unit::TestCase + include UpdateEnv + def setup - ENV['REQUEST_METHOD'] = 'POST' + @environ = {} + update_env( + 'REQUEST_METHOD' => 'POST', + 'CONTENT_TYPE' => nil, + 'CONTENT_LENGTH' => nil, + ) @tempfiles = [] end def teardown - %w[ REQUEST_METHOD CONTENT_TYPE CONTENT_LENGTH REQUEST_METHOD ].each do |name| - ENV.delete(name) - end + ENV.update(@environ) $stdin.close() if $stdin.is_a?(Tempfile) $stdin = STDIN @tempfiles.each {|t| @@ -196,7 +202,7 @@ class CGIMultipartTest < Test::Unit::TestCase @boundary = '----WebKitFormBoundaryAAfvAII+YL9102cX' @data = [ {:name=>'hidden1', :value=>'foobar'}, - {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A"}, + {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A".dup}, {:name=>'file1', :value=>_read('file1.html'), :filename=>'file1.html', :content_type=>'text/html'}, {:name=>'image1', :value=>_read('small.png'), @@ -212,7 +218,7 @@ class CGIMultipartTest < Test::Unit::TestCase @boundary = '----WebKitFormBoundaryAAfvAII+YL9102cX' @data = [ {:name=>'hidden1', :value=>'foobar'}, - {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A"}, + {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A".dup}, {:name=>'file1', :value=>_read('file1.html'), :filename=>'file1.html', :content_type=>'text/html'}, {:name=>'image1', :value=>_read('large.png'), @@ -317,7 +323,7 @@ class CGIMultipartTest < Test::Unit::TestCase @boundary = '(.|\n)*' @data = [ {:name=>'hidden1', :value=>'foobar'}, - {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A"}, + {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A".dup}, {:name=>'file1', :value=>_read('file1.html'), :filename=>'file1.html', :content_type=>'text/html'}, {:name=>'image1', :value=>_read('small.png'), @@ -349,7 +355,7 @@ class CGIMultipartTest < Test::Unit::TestCase require 'stringio' ENV['REQUEST_METHOD'] = 'POST' ENV['CONTENT_TYPE'] = 'multipart/form-data; boundary=foobar1234' - body = <<-BODY + body = <<-BODY.gsub(/\n/, "\r\n") --foobar1234 Content-Disposition: form-data: name=\"name1\" @@ -364,7 +370,6 @@ Content-Type: text/html --foobar1234-- BODY - body.gsub!(/\n/, "\r\n") ENV['CONTENT_LENGTH'] = body.size.to_s $stdin = StringIO.new(body) CGI.new diff --git a/test/cgi/test_cgi_session.rb b/test/cgi/test_cgi_session.rb index 8bd51776ff..b16b69766e 100644 --- a/test/cgi/test_cgi_session.rb +++ b/test/cgi/test_cgi_session.rb @@ -1,33 +1,37 @@ +# frozen_string_literal: true require 'test/unit' require 'cgi' require 'cgi/session' require 'cgi/session/pstore' require 'stringio' require 'tmpdir' +require_relative 'update_env' class CGISessionTest < Test::Unit::TestCase + include UpdateEnv + def setup + @environ = {} @session_dir = Dir.mktmpdir(%w'session dir') end def teardown - @environ.each do |key, val| ENV.delete(key) end + ENV.update(@environ) $stdout = STDOUT FileUtils.rm_rf(@session_dir) end def test_cgi_session_filestore - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', # 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F', # 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;', 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } + ) value1="value1" - value2="\x8F\xBC\x8D]" + value2="\x8F\xBC\x8D]".dup value2.force_encoding("SJIS") if defined?(::Encoding) - ENV.update(@environ) cgi = CGI.new session = CGI::Session.new(cgi,"tmpdir"=>@session_dir) session["key1"]=value1 @@ -38,14 +42,13 @@ class CGISessionTest < Test::Unit::TestCase $stdout = StringIO.new cgi.out{""} - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', # 'HTTP_COOKIE' => "_session_id=#{session_id}", 'QUERY_STRING' => "_session_id=#{session.session_id}", 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } - ENV.update(@environ) + ) cgi = CGI.new session = CGI::Session.new(cgi,"tmpdir"=>@session_dir) $stdout = StringIO.new @@ -55,17 +58,16 @@ class CGISessionTest < Test::Unit::TestCase end def test_cgi_session_pstore - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', # 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F', # 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;', 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } + ) value1="value1" - value2="\x8F\xBC\x8D]" + value2="\x8F\xBC\x8D]".dup value2.force_encoding("SJIS") if defined?(::Encoding) - ENV.update(@environ) cgi = CGI.new session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"database_manager"=>CGI::Session::PStore) session["key1"]=value1 @@ -76,14 +78,13 @@ class CGISessionTest < Test::Unit::TestCase $stdout = StringIO.new cgi.out{""} - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', # 'HTTP_COOKIE' => "_session_id=#{session_id}", 'QUERY_STRING' => "_session_id=#{session.session_id}", 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } - ENV.update(@environ) + ) cgi = CGI.new session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"database_manager"=>CGI::Session::PStore) $stdout = StringIO.new @@ -92,17 +93,16 @@ class CGISessionTest < Test::Unit::TestCase session.close end def test_cgi_session_specify_session_id - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', # 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F', # 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;', 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } + ) value1="value1" - value2="\x8F\xBC\x8D]" + value2="\x8F\xBC\x8D]".dup value2.force_encoding("SJIS") if defined?(::Encoding) - ENV.update(@environ) cgi = CGI.new session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"session_id"=>"foo") session["key1"]=value1 @@ -115,14 +115,13 @@ class CGISessionTest < Test::Unit::TestCase $stdout = StringIO.new cgi.out{""} - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', # 'HTTP_COOKIE' => "_session_id=#{session_id}", 'QUERY_STRING' => "_session_id=#{session.session_id}", 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } - ENV.update(@environ) + ) cgi = CGI.new session = CGI::Session.new(cgi,"tmpdir"=>@session_dir) $stdout = StringIO.new @@ -132,17 +131,16 @@ class CGISessionTest < Test::Unit::TestCase session.close end def test_cgi_session_specify_session_key - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', # 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F', # 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;', 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } + ) value1="value1" - value2="\x8F\xBC\x8D]" + value2="\x8F\xBC\x8D]".dup value2.force_encoding("SJIS") if defined?(::Encoding) - ENV.update(@environ) cgi = CGI.new session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"session_key"=>"bar") session["key1"]=value1 @@ -154,14 +152,13 @@ class CGISessionTest < Test::Unit::TestCase $stdout = StringIO.new cgi.out{""} - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', 'HTTP_COOKIE' => "bar=#{session_id}", # 'QUERY_STRING' => "bar=#{session.session_id}", 'SERVER_SOFTWARE' => 'Apache 2.2.0', 'SERVER_PROTOCOL' => 'HTTP/1.1', - } - ENV.update(@environ) + ) cgi = CGI.new session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"session_key"=>"bar") $stdout = StringIO.new diff --git a/test/cgi/test_cgi_tag_helper.rb b/test/cgi/test_cgi_tag_helper.rb index eb3c20a02e..0b99dfc1bc 100644 --- a/test/cgi/test_cgi_tag_helper.rb +++ b/test/cgi/test_cgi_tag_helper.rb @@ -1,12 +1,16 @@ +# frozen_string_literal: true require 'test/unit' require 'cgi' require 'stringio' +require_relative 'update_env' class CGITagHelperTest < Test::Unit::TestCase + include UpdateEnv def setup + @environ = {} #@environ = { # 'SERVER_PROTOCOL' => 'HTTP/1.1', # 'REQUEST_METHOD' => 'GET', @@ -17,16 +21,15 @@ class CGITagHelperTest < Test::Unit::TestCase def teardown - @environ.each do |key, val| ENV.delete(key) end + ENV.update(@environ) $stdout = STDOUT end def test_cgi_tag_helper_html3 - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', - } - ENV.update(@environ) + ) ## html3 cgi = CGI.new('html3') assert_equal('<A HREF=""></A>',cgi.a) @@ -337,10 +340,9 @@ class CGITagHelperTest < Test::Unit::TestCase =end def test_cgi_tag_helper_html5 - @environ = { + update_env( 'REQUEST_METHOD' => 'GET', - } - ENV.update(@environ) + ) ## html5 cgi = CGI.new('html5') assert_equal('<HEADER></HEADER>',cgi.header) diff --git a/test/cgi/test_cgi_util.rb b/test/cgi/test_cgi_util.rb index 802379d233..d058cccd86 100644 --- a/test/cgi/test_cgi_util.rb +++ b/test/cgi/test_cgi_util.rb @@ -1,68 +1,217 @@ +# frozen_string_literal: true require 'test/unit' require 'cgi' require 'stringio' +require_relative 'update_env' class CGIUtilTest < Test::Unit::TestCase include CGI::Util + include UpdateEnv def setup - ENV['REQUEST_METHOD'] = 'GET' - @str1="&<>\" \xE3\x82\x86\xE3\x82\x93\xE3\x82\x86\xE3\x82\x93" + @environ = {} + update_env( + 'REQUEST_METHOD' => 'GET', + 'SCRIPT_NAME' => nil, + ) + @str1="&<>\" \xE3\x82\x86\xE3\x82\x93\xE3\x82\x86\xE3\x82\x93".dup @str1.force_encoding("UTF-8") if defined?(::Encoding) end def teardown - %W[REQUEST_METHOD SCRIPT_NAME].each do |name| - ENV.delete(name) - end + ENV.update(@environ) end - def test_cgi_escape - assert_equal('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93', CGI::escape(@str1)) - assert_equal('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93'.ascii_only?, CGI::escape(@str1).ascii_only?) if defined?(::Encoding) + assert_equal('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93', CGI.escape(@str1)) + assert_equal('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93'.ascii_only?, CGI.escape(@str1).ascii_only?) if defined?(::Encoding) + end + + def test_cgi_escape_with_unreserved_characters + assert_equal("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~", + CGI.escape("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"), + "should not escape any unreserved characters, as per RFC3986 Section 2.3") end def test_cgi_escape_with_invalid_byte_sequence - assert_nothing_raised(ArgumentError) do - assert_equal('%C0%3C%3C', CGI::escape("\xC0\<\<".force_encoding("UTF-8"))) - end + assert_equal('%C0%3C%3C', CGI.escape("\xC0\<\<".dup.force_encoding("UTF-8"))) end def test_cgi_escape_preserve_encoding - assert_equal(Encoding::US_ASCII, CGI::escape("\xC0\<\<".force_encoding("US-ASCII")).encoding) - assert_equal(Encoding::ASCII_8BIT, CGI::escape("\xC0\<\<".force_encoding("ASCII-8BIT")).encoding) - assert_equal(Encoding::UTF_8, CGI::escape("\xC0\<\<".force_encoding("UTF-8")).encoding) + assert_equal(Encoding::US_ASCII, CGI.escape("\xC0\<\<".dup.force_encoding("US-ASCII")).encoding) + assert_equal(Encoding::ASCII_8BIT, CGI.escape("\xC0\<\<".dup.force_encoding("ASCII-8BIT")).encoding) + assert_equal(Encoding::UTF_8, CGI.escape("\xC0\<\<".dup.force_encoding("UTF-8")).encoding) end def test_cgi_unescape - assert_equal(@str1, CGI::unescape('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93')) - assert_equal(@str1.encoding, CGI::unescape('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93').encoding) if defined?(::Encoding) + str = CGI.unescape('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93') + assert_equal(@str1, str) + return unless defined?(::Encoding) + + assert_equal(@str1.encoding, str.encoding) assert_equal("\u{30E1 30E2 30EA 691C 7D22}", CGI.unescape("\u{30E1 30E2 30EA}%E6%A4%9C%E7%B4%A2")) end def test_cgi_unescape_preserve_encoding - assert_equal(Encoding::US_ASCII, CGI::unescape("%C0%3C%3C".force_encoding("US-ASCII")).encoding) - assert_equal(Encoding::ASCII_8BIT, CGI::unescape("%C0%3C%3C".force_encoding("ASCII-8BIT")).encoding) - assert_equal(Encoding::UTF_8, CGI::unescape("%C0%3C%3C".force_encoding("UTF-8")).encoding) + assert_equal(Encoding::US_ASCII, CGI.unescape("%C0%3C%3C".dup.force_encoding("US-ASCII")).encoding) + assert_equal(Encoding::ASCII_8BIT, CGI.unescape("%C0%3C%3C".dup.force_encoding("ASCII-8BIT")).encoding) + assert_equal(Encoding::UTF_8, CGI.unescape("%C0%3C%3C".dup.force_encoding("UTF-8")).encoding) + end + + def test_cgi_unescape_accept_charset + return unless defined?(::Encoding) + + assert_raise(TypeError) {CGI.unescape('', nil)} + assert_separately(%w[-rcgi/util], "#{<<-"begin;"}\n#{<<-"end;"}") + begin; + assert_equal("", CGI.unescape('')) + end; + end + + def test_cgi_escapeURIComponent + assert_equal('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93', CGI.escapeURIComponent(@str1)) + 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) + end + + def test_cgi_escapeURIComponent_with_unreserved_characters + assert_equal("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~", + CGI.escapeURIComponent("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"), + "should not encode any unreserved characters, as per RFC3986 Section 2.3") + end + + def test_cgi_escapeURIComponent_with_invalid_byte_sequence + assert_equal('%C0%3C%3C', CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("UTF-8"))) + end + + def test_cgi_escapeURIComponent_preserve_encoding + assert_equal(Encoding::US_ASCII, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("US-ASCII")).encoding) + assert_equal(Encoding::ASCII_8BIT, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("ASCII-8BIT")).encoding) + assert_equal(Encoding::UTF_8, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("UTF-8")).encoding) + end + + def test_cgi_unescapeURIComponent + str = CGI.unescapeURIComponent('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93') + assert_equal(@str1, str) + return unless defined?(::Encoding) + + assert_equal("foo+bar", CGI.unescapeURIComponent("foo+bar")) + + assert_equal(@str1.encoding, str.encoding) + assert_equal("\u{30E1 30E2 30EA 691C 7D22}", CGI.unescapeURIComponent("\u{30E1 30E2 30EA}%E6%A4%9C%E7%B4%A2")) + end + + def test_cgi_unescapeURIComponent_preserve_encoding + assert_equal(Encoding::US_ASCII, CGI.unescapeURIComponent("%C0%3C%3C".dup.force_encoding("US-ASCII")).encoding) + assert_equal(Encoding::ASCII_8BIT, CGI.unescapeURIComponent("%C0%3C%3C".dup.force_encoding("ASCII-8BIT")).encoding) + assert_equal(Encoding::UTF_8, CGI.unescapeURIComponent("%C0%3C%3C".dup.force_encoding("UTF-8")).encoding) + end + + def test_cgi_unescapeURIComponent_accept_charset + return unless defined?(::Encoding) + + assert_raise(TypeError) {CGI.unescapeURIComponent('', nil)} + assert_separately(%w[-rcgi/util], "#{<<-"begin;"}\n#{<<-"end;"}") + begin; + assert_equal("", CGI.unescapeURIComponent('')) + end; end def test_cgi_pretty - assert_equal("<HTML>\n <BODY>\n </BODY>\n</HTML>\n",CGI::pretty("<HTML><BODY></BODY></HTML>")) - assert_equal("<HTML>\n\t<BODY>\n\t</BODY>\n</HTML>\n",CGI::pretty("<HTML><BODY></BODY></HTML>","\t")) + assert_equal("<HTML>\n <BODY>\n </BODY>\n</HTML>\n",CGI.pretty("<HTML><BODY></BODY></HTML>")) + assert_equal("<HTML>\n\t<BODY>\n\t</BODY>\n</HTML>\n",CGI.pretty("<HTML><BODY></BODY></HTML>","\t")) end def test_cgi_escapeHTML - assert_equal(CGI::escapeHTML("'&\"><"),"'&"><") + assert_equal("'&"><", CGI.escapeHTML("'&\"><")) + end + + def test_cgi_escape_html_duplicated + orig = "Ruby".dup.force_encoding("US-ASCII") + str = CGI.escapeHTML(orig) + assert_equal(orig, str) + assert_not_same(orig, str) + end + + def assert_cgi_escape_html_preserve_encoding(str, encoding) + assert_equal(encoding, CGI.escapeHTML(str.dup.force_encoding(encoding)).encoding) + end + + def test_cgi_escape_html_preserve_encoding + Encoding.list do |enc| + assert_cgi_escape_html_preserve_encoding("'&\"><", enc) + assert_cgi_escape_html_preserve_encoding("Ruby", enc) + end + end + + def test_cgi_escape_html_dont_freeze + assert_not_predicate CGI.escapeHTML("'&\"><".dup), :frozen? + assert_not_predicate CGI.escapeHTML("'&\"><".freeze), :frozen? + assert_not_predicate CGI.escapeHTML("Ruby".dup), :frozen? + assert_not_predicate CGI.escapeHTML("Ruby".freeze), :frozen? + end + + def test_cgi_escape_html_large + return if RUBY_ENGINE == 'jruby' + ulong_max, size_max = RbConfig::LIMITS.values_at("ULONG_MAX", "SIZE_MAX") + return unless ulong_max < size_max # Platforms not concerned + + size = (ulong_max / 6 + 1) + begin + str = '"' * size + escaped = CGI.escapeHTML(str) + rescue NoMemoryError + omit "Not enough memory" + rescue => e + end + assert_raise_with_message(ArgumentError, /overflow/, ->{"length = #{escaped.length}"}) do + raise e if e + end end def test_cgi_unescapeHTML - assert_equal(CGI::unescapeHTML("'&"><"),"'&\"><") + assert_equal("'&\"><", CGI.unescapeHTML("'&"><")) + end + + def test_cgi_unescapeHTML_invalid + assert_equal('&<&>"&abcdefghijklmn', CGI.unescapeHTML('&<&>"&abcdefghijklmn')) + end + + Encoding.list.each do |enc| + begin + escaped = "'&"><".encode(enc) + unescaped = "'&\"><".encode(enc) + rescue Encoding::ConverterNotFoundError + next + else + define_method("test_cgi_escapeHTML:#{enc.name}") do + assert_equal(escaped, CGI.escapeHTML(unescaped)) + end + define_method("test_cgi_unescapeHTML:#{enc.name}") do + assert_equal(unescaped, CGI.unescapeHTML(escaped)) + end + end + end + + Encoding.list.each do |enc| + next unless enc.ascii_compatible? + begin + escaped = "%25+%2B" + unescaped = "% +".encode(enc) + rescue Encoding::ConverterNotFoundError + next + else + define_method("test_cgi_escape:#{enc.name}") do + assert_equal(escaped, CGI.escape(unescaped)) + end + define_method("test_cgi_unescape:#{enc.name}") do + assert_equal(unescaped, CGI.unescape(escaped, enc)) + end + end end def test_cgi_unescapeHTML_uppercasecharacter - assert_equal(CGI::unescapeHTML("あいう"),"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86") + assert_equal("\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86", CGI.unescapeHTML("あいう")) end def test_cgi_include_escape @@ -70,21 +219,24 @@ class CGIUtilTest < Test::Unit::TestCase end def test_cgi_include_escapeHTML - assert_equal(escapeHTML("'&\"><"),"'&"><") + assert_equal("'&"><", escapeHTML("'&\"><")) end def test_cgi_include_h - assert_equal(h("'&\"><"),"'&"><") + assert_equal("'&"><", h("'&\"><")) end def test_cgi_include_unescape - assert_equal(@str1, unescape('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93')) - assert_equal(@str1.encoding, unescape('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93').encoding) if defined?(::Encoding) + str = unescape('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93') + assert_equal(@str1, str) + return unless defined?(::Encoding) + + assert_equal(@str1.encoding, str.encoding) assert_equal("\u{30E1 30E2 30EA 691C 7D22}", unescape("\u{30E1 30E2 30EA}%E6%A4%9C%E7%B4%A2")) end def test_cgi_include_unescapeHTML - assert_equal(unescapeHTML("'&"><"),"'&\"><") + assert_equal("'&\"><", unescapeHTML("'&"><")) end def test_cgi_escapeElement @@ -92,6 +244,14 @@ class CGIUtilTest < Test::Unit::TestCase assert_equal("<BR><A HREF="url"></A>", escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])) assert_equal("<BR><A HREF="url"></A>", escape_element('<BR><A HREF="url"></A>', "A", "IMG")) assert_equal("<BR><A HREF="url"></A>", escape_element('<BR><A HREF="url"></A>', ["A", "IMG"])) + + assert_equal("<A <A HREF="url"></A>", escapeElement('<A <A HREF="url"></A>', "A", "IMG")) + assert_equal("<A <A HREF="url"></A>", escapeElement('<A <A HREF="url"></A>', ["A", "IMG"])) + assert_equal("<A <A HREF="url"></A>", escape_element('<A <A HREF="url"></A>', "A", "IMG")) + assert_equal("<A <A HREF="url"></A>", escape_element('<A <A HREF="url"></A>', ["A", "IMG"])) + + assert_equal("<A <A ", escapeElement('<A <A ', "A", "IMG")) + assert_equal("<A <A ", escapeElement('<A <A ', ["A", "IMG"])) end @@ -100,5 +260,44 @@ class CGIUtilTest < Test::Unit::TestCase assert_equal('<BR><A HREF="url"></A>', unescapeElement(escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])) assert_equal('<BR><A HREF="url"></A>', unescape_element(escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")) assert_equal('<BR><A HREF="url"></A>', unescape_element(escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])) + + assert_equal('<A <A HREF="url"></A>', unescapeElement(escapeHTML('<A <A HREF="url"></A>'), "A", "IMG")) + assert_equal('<A <A HREF="url"></A>', unescapeElement(escapeHTML('<A <A HREF="url"></A>'), ["A", "IMG"])) + assert_equal('<A <A HREF="url"></A>', unescape_element(escapeHTML('<A <A HREF="url"></A>'), "A", "IMG")) + assert_equal('<A <A HREF="url"></A>', unescape_element(escapeHTML('<A <A HREF="url"></A>'), ["A", "IMG"])) + + assert_equal('<A <A ', unescapeElement(escapeHTML('<A <A '), "A", "IMG")) + assert_equal('<A <A ', unescapeElement(escapeHTML('<A <A '), ["A", "IMG"])) + assert_equal('<A <A ', unescape_element(escapeHTML('<A <A '), "A", "IMG")) + assert_equal('<A <A ', unescape_element(escapeHTML('<A <A '), ["A", "IMG"])) + end +end + +class CGIUtilPureRubyTest < Test::Unit::TestCase + def setup + CGI::Escape.module_eval do + alias _escapeHTML escapeHTML + remove_method :escapeHTML + alias _unescapeHTML unescapeHTML + remove_method :unescapeHTML + end + end + + def teardown + CGI::Escape.module_eval do + alias escapeHTML _escapeHTML + remove_method :_escapeHTML + alias unescapeHTML _unescapeHTML + remove_method :_unescapeHTML + end + end + + def test_cgi_escapeHTML_with_invalid_byte_sequence + assert_equal("<\xA4??>", CGI.escapeHTML(%[<\xA4??>])) + end + + def test_cgi_unescapeHTML_with_invalid_byte_sequence + input = "\xFF&" + assert_equal(input, CGI.unescapeHTML(input)) end end diff --git a/test/cgi/update_env.rb b/test/cgi/update_env.rb new file mode 100644 index 0000000000..cbc8dc13c6 --- /dev/null +++ b/test/cgi/update_env.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: false +module UpdateEnv + def update_env(environ) + environ.each do |key, val| + @environ[key] = ENV[key] unless @environ.key?(key) + ENV[key] = val + end + end +end |
