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

ruby-changes:14047

From: shugo <ko1@a...>
Date: Thu, 19 Nov 2009 22:38:46 +0900 (JST)
Subject: [ruby-changes:14047] Ruby:r25858 (ruby_1_8): * lib/net/imap.rb (flag_list): untaint strings to intern in the safe

shugo	2009-11-19 22:38:35 +0900 (Thu, 19 Nov 2009)

  New Revision: 25858

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

  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:
    branches/ruby_1_8/test/net/imap/test_imap_response_parser.rb
  Modified files:
    branches/ruby_1_8/lib/net/imap.rb

Index: ruby_1_8/lib/net/imap.rb
===================================================================
--- ruby_1_8/lib/net/imap.rb	(revision 25857)
+++ ruby_1_8/lib/net/imap.rb	(revision 25858)
@@ -269,6 +269,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
@@ -858,6 +868,7 @@
 
     @@debug = false
     @@authenticators = {}
+    @@max_flag_count = 10000
 
     # Creates a new Net::IMAP object and connects it to the specified
     # +port+ (143 by default) on the named +host+.  If +usessl+ is true, 
@@ -1868,6 +1879,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
@@ -2878,7 +2897,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")
@@ -3223,6 +3251,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: ruby_1_8/test/net/imap/test_imap_response_parser.rb
===================================================================
--- ruby_1_8/test/net/imap/test_imap_response_parser.rb	(revision 0)
+++ ruby_1_8/test/net/imap/test_imap_response_parser.rb	(revision 25858)
@@ -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/

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