From: Makoto Kuwata Date: 2007-12-07T01:13:21+09:00 Subject: [ruby-list:44321] Re: multipartで送信した時のRails/cgi.rbの動作について 桑田です。 On Dec 6, 2007 5:36 PM, KOSEKI Kengo wrote: > 最初はStringIOに入れておいて、そのフィールドの入力が > 一定サイズを超えたらTempfileに移行するといいのではと > 思ったんですが、、。 Ruby1.9のcgi.rbはそのような動作になっているみたいです。 > > 試しにパッチを作成してみました。Ruby1.8.6のcgi.rbをもとにしています。 > >ありがとうございます! >試してみます。 新しいパッチを作ったので、こちらを試していただけますか。 multipartでない場合でも、REQUEST_METHODが "POST" なら CONTENT_LENGTH の 長さを調べ、長過ぎるようならエラーにしています。 multipartの場合とそうでない場合とで、制限値を変えています。 Index: lib/cgi.rb =================================================================== --- /user/local/lib/ruby/1.8/cgi.rb 2007-05-23 06:58:09.000000000 +0900 +++ lib/cgi.rb 2007-12-07 01:00:37.000000000 +0900 @@ -907,6 +907,17 @@ params end + + # Maximum content length of post data + MAX_CONTENT_LENGTH = 2 * 1024 * 1024 + + # Maximum content length of multipart data + MAX_MULTIPART_LENGTH = 128 * 1024 * 1024 + + # Maximum number of parameters when multipart + MAX_MULTIPART_COUNT = 128 + + # Mixin module. It provides the follow functionality groups: # # 1. Access to CGI environment variables as methods. See @@ -984,9 +995,14 @@ raise EOFError, "bad content body" end + max_count = MAX_MULTIPART_COUNT + n = 0 + loop do + raise StandardError.new("too many parameters.") if (n += 1) > max_count + head = nil - if 10240 < content_length + if bufsize < content_length require "tempfile" body = Tempfile.new("CGI") else @@ -1106,7 +1122,11 @@ %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(env_table['CONTENT_TYPE']) boundary = $1.dup @multipart = true - @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH'])) + content_length = Integer(env_table['CONTENT_LENGTH']) + if content_length > MAX_MULTIPART_LENGTH + raise StandardError.new("too large multipart data.") + end + @params = read_multipart(boundary, content_length) else @multipart = false @params = CGI::parse( @@ -1118,8 +1138,12 @@ env_table['QUERY_STRING'] or "" end when "POST" + content_length = Integer(env_table['CONTENT_LENGTH']) + if content_length > MAX_CONTENT_LENGTH + raise StandardError.new("too large post data.") + end stdinput.binmode if defined? stdinput.binmode - stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or '' + stdinput.read(content_length) or '' else read_from_cmdline end =================================================================== これに関連する話ですが、以前質問したときに cgi.rb のテストスクリプトは 存在しないといわれたので、今 cgi.rb のテストスクリプトを書いています。 そのうち公開すると思います。 -- makoto kuwata