[前][次][番号順一覧][スレッド一覧]

ruby-changes:14049

From: shugo <ko1@a...>
Date: Thu, 19 Nov 2009 23:06:20 +0900 (JST)
Subject: [ruby-changes:14049] Ruby:r25860 (trunk): * lib/net/imap.rb (flag_list): untaint strings to intern in the safe

shugo	2009-11-19 22:56:23 +0900 (Thu, 19 Nov 2009)

  New Revision: 25860

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=25860

  Log:
    * lib/net/imap.rb (flag_list): untaint strings to intern in the safe
      level 1.
    * lib/net/imap.rb (max_flag_count=): new methods to set the max
      number of flags interned to symbols.

  Added files:
    trunk/test/net/imap/test_imap_response_parser.rb
  Modified files:
    trunk/lib/net/imap.rb

Index: lib/net/imap.rb
===================================================================
--- lib/net/imap.rb	(revision 25859)
+++ lib/net/imap.rb	(revision 25860)
@@ -270,6 +270,16 @@
       return @@debug = val
     end
 
+    # Returns the max number of flags interned to symbols.
+    def self.max_flag_count
+      return @@max_flag_count
+    end
+
+    # Sets the max number of flags interned to symbols.
+    def self.max_flag_count=(count)
+      @@max_flag_count = count
+    end
+
     # Adds an authenticator for Net::IMAP#authenticate.  +auth_type+
     # is the type of authentication this authenticator supports
     # (for instance, "LOGIN").  The +authenticator+ is an object
@@ -929,6 +939,7 @@
 
     @@debug = false
     @@authenticators = {}
+    @@max_flag_count = 10000
 
     # call-seq:
     #    Net::IMAP.new(host, options = {})
@@ -1929,6 +1940,14 @@
     end
 
     class ResponseParser # :nodoc:
+      def initialize
+        @str = nil
+        @pos = nil
+        @lex_state = nil
+        @token = nil
+        @flag_symbols = {}
+      end
+
       def parse(str)
         @str = str
         @pos = 0
@@ -2939,7 +2958,16 @@
         if @str.index(/\(([^)]*)\)/ni, @pos)
           @pos = $~.end(0)
           return $1.scan(FLAG_REGEXP).collect { |flag, atom|
-            atom || flag.capitalize.intern
+            if atom
+              atom
+            else
+              symbol = flag.capitalize.untaint.intern
+              @flag_symbols[symbol] = true
+              if @flag_symbols.length > IMAP.max_flag_count
+                raise FlagCountError, "number of flag symbols exceeded"
+              end
+              symbol
+            end
           }
         else
           parse_error("invalid flag list")
@@ -3410,6 +3438,10 @@
     # out due to inactivity.
     class ByeResponseError < ResponseError
     end
+
+    # Error raised when too many flags are interned to symbols.
+    class FlagCountError < Error
+    end
   end
 end
 
Index: test/net/imap/test_imap_response_parser.rb
===================================================================
--- test/net/imap/test_imap_response_parser.rb	(revision 0)
+++ test/net/imap/test_imap_response_parser.rb	(revision 25860)
@@ -0,0 +1,54 @@
+require "net/imap"
+require "test/unit"
+
+class IMAPResponseParserTest < Test::Unit::TestCase
+  def setup
+    @do_not_reverse_lookup = Socket.do_not_reverse_lookup
+    Socket.do_not_reverse_lookup = true
+    @max_flag_count = Net::IMAP.max_flag_count
+    Net::IMAP.max_flag_count = 3
+  end
+
+  def teardown
+    Socket.do_not_reverse_lookup = @do_not_reverse_lookup
+    Net::IMAP.max_flag_count = @max_flag_count
+  end
+
+  def test_flag_list_safe
+    parser = Net::IMAP::ResponseParser.new
+    response = lambda {
+      $SAFE = 1
+      parser.parse(<<EOF.gsub(/\n/, "\r\n").taint)
+* LIST (\\HasChildren) "." "INBOX"
+EOF
+    }.call
+    assert_equal [:Haschildren], response.data.attr
+  end
+
+  def test_flag_list_too_many_flags
+    parser = Net::IMAP::ResponseParser.new
+    assert_nothing_raised do
+      3.times do |i|
+      parser.parse(<<EOF.gsub(/\n/, "\r\n").taint)
+* LIST (\\Foo#{i}) "." "INBOX"
+EOF
+      end
+    end
+    assert_raise(Net::IMAP::FlagCountError) do
+      parser.parse(<<EOF.gsub(/\n/, "\r\n").taint)
+* LIST (\\Foo3) "." "INBOX"
+EOF
+    end
+  end
+
+  def test_flag_list_many_same_flags
+    parser = Net::IMAP::ResponseParser.new
+    assert_nothing_raised do
+      100.times do
+      parser.parse(<<EOF.gsub(/\n/, "\r\n").taint)
+* LIST (\\Foo) "." "INBOX"
+EOF
+      end
+    end
+  end
+end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]