diff options
Diffstat (limited to 'activesupport')
10 files changed, 77 insertions, 18 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 08bec2f4ae..5848f9712f 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,12 @@ ## Rails 4.0.0 (unreleased) ## +* Hash.from_xml raises when it encounters type="symbol" or type="yaml". + Use Hash.from_trusted_xml to parse this XML. + + CVE-2013-0156 + + *Jeremy Kemper* + * Deprecate `assert_present` and `assert_blank` in favor of `assert object.blank?` and `assert object.present?` diff --git a/activesupport/lib/active_support/backtrace_cleaner.rb b/activesupport/lib/active_support/backtrace_cleaner.rb index f1aff8a8e3..4b41e6247d 100644 --- a/activesupport/lib/active_support/backtrace_cleaner.rb +++ b/activesupport/lib/active_support/backtrace_cleaner.rb @@ -72,6 +72,9 @@ module ActiveSupport @silencers = [] end + # Removes all filters, but leaves in silencers. Useful if you suddenly + # need to see entire filepaths in the backtrace that you had already + # filtered out. def remove_filters! @filters = [] end diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index 64e9945ef5..430a35fbaf 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -8,7 +8,7 @@ class Array # Converts the array to a comma-separated sentence where the last element is # joined by the connector word. # - # You can pass the following options to change the default behaviour. If you + # You can pass the following options to change the default behavior. If you # pass an option key that doesn't exist in the list below, it will raise an # <tt>ArgumentError</tt>. # diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index 6cb7434e5f..8930376ac8 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -101,17 +101,33 @@ class Hash # # hash = Hash.from_xml(xml) # # => {"hash"=>{"foo"=>1, "bar"=>2}} - def from_xml(xml) - ActiveSupport::XMLConverter.new(xml).to_h + # + # DisallowedType is raise if the XML contains attributes with <tt>type="yaml"</tt> or + # <tt>type="symbol"</tt>. Use <tt>Hash.from_trusted_xml</tt> to parse this XML. + def from_xml(xml, disallowed_types = nil) + ActiveSupport::XMLConverter.new(xml, disallowed_types).to_h end + # Builds a Hash from XML just like <tt>Hash.from_xml</tt>, but also allows Symbol and YAML. + def from_trusted_xml(xml) + from_xml xml, [] + end end end module ActiveSupport class XMLConverter # :nodoc: - def initialize(xml) + class DisallowedType < StandardError + def initialize(type) + super "Disallowed type attribute: #{type.inspect}" + end + end + + DISALLOWED_TYPES = %w(symbol yaml) + + def initialize(xml, disallowed_types = nil) @xml = normalize_keys(XmlMini.parse(xml)) + @disallowed_types = disallowed_types || DISALLOWED_TYPES end def to_h @@ -119,7 +135,6 @@ module ActiveSupport end private - def normalize_keys(params) case params when Hash @@ -145,6 +160,10 @@ module ActiveSupport end def process_hash(value) + if value.include?('type') && !value['type'].is_a?(Hash) && @disallowed_types.include?(value['type']) + raise DisallowedType, value['type'] + end + if become_array?(value) _, entries = Array.wrap(value.detect { |k,v| not v.is_a?(String) }) if entries.nil? || value['__content__'].try(:empty?) diff --git a/activesupport/lib/active_support/core_ext/object/acts_like.rb b/activesupport/lib/active_support/core_ext/object/acts_like.rb index fcc8e50f06..3912cc5ace 100644 --- a/activesupport/lib/active_support/core_ext/object/acts_like.rb +++ b/activesupport/lib/active_support/core_ext/object/acts_like.rb @@ -1,9 +1,9 @@ class Object # A duck-type assistant method. For example, Active Support extends Date - # to define an acts_like_date? method, and extends Time to define - # acts_like_time?. As a result, we can do "x.acts_like?(:time)" and - # "x.acts_like?(:date)" to do duck-type-safe comparisons, since classes that - # we want to act like Time simply need to define an acts_like_time? method. + # to define an <tt>acts_like_date?</tt> method, and extends Time to define + # <tt>acts_like_time?</tt>. As a result, we can do <tt>x.acts_like?(:time)</tt> and + # <tt>x.acts_like?(:date)</tt> to do duck-type-safe comparisons, since classes that + # we want to act like Time simply need to define an <tt>acts_like_time?</tt> method. def acts_like?(duck) respond_to? :"acts_like_#{duck}?" end diff --git a/activesupport/lib/active_support/core_ext/object/instance_variables.rb b/activesupport/lib/active_support/core_ext/object/instance_variables.rb index 40821fd619..755e1c6b16 100644 --- a/activesupport/lib/active_support/core_ext/object/instance_variables.rb +++ b/activesupport/lib/active_support/core_ext/object/instance_variables.rb @@ -13,7 +13,7 @@ class Object Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }] end - # Returns an array of instance variable names including "@". + # Returns an array of instance variable names as strings including "@". # # class C # def initialize(x, y) diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 832d1ce6d5..9bf1ea35b3 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -235,7 +235,7 @@ class BigDecimal # real value. # # Use <tt>ActiveSupport.use_standard_json_big_decimal_format = true</tt> to - # override this behaviour. + # override this behavior. def as_json(options = nil) #:nodoc: if finite? ActiveSupport.encode_big_decimal_as_string ? to_s : self diff --git a/activesupport/lib/active_support/log_subscriber/test_helper.rb b/activesupport/lib/active_support/log_subscriber/test_helper.rb index 63dad7e01a..f9a98686d3 100644 --- a/activesupport/lib/active_support/log_subscriber/test_helper.rb +++ b/activesupport/lib/active_support/log_subscriber/test_helper.rb @@ -15,7 +15,7 @@ module ActiveSupport # end # # def test_basic_query_logging - # Developer.all + # Developer.all.to_a # wait # assert_equal 1, @logger.logged(:debug).size # assert_match(/Developer Load/, @logger.logged(:debug).last) diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index fdaaacf2fe..d3741845d2 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -109,6 +109,14 @@ module ActiveSupport alias_method :gmt_offset, :utc_offset alias_method :gmtoff, :utc_offset + # Returns a formatted string of the offset from UTC, or an alternative + # string if the time zone is already UTC. + # + # Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)" + # Time.zone.now.formatted_offset(true) # => "-05:00" + # Time.zone.now.formatted_offset(false) # => "-0500" + # Time.zone = 'UTC' # => "UTC" + # Time.zone.now.formatted_offset(true, "0") # => "0" def formatted_offset(colon = true, alternate_utc_string = nil) utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon) end @@ -206,18 +214,24 @@ module ActiveSupport utc <=> other end + # Returns true if the current object's time is within the specified + # +min+ and +max+ time. def between?(min, max) utc.between?(min, max) end + # Returns true if the current object's time is in the past. def past? utc.past? end + # Returns true if the current object's time falls within + # the current day. def today? time.today? end + # Returns true if the current object's time is in the future. def future? utc.future? end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 84dd9bc983..30d95b75bc 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -1015,12 +1015,10 @@ class HashToXmlTest < ActiveSupport::TestCase <replies-close-in type="integer">2592000000</replies-close-in> <written-on type="date">2003-07-16</written-on> <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at> - <content type="yaml">--- \n1: should be an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n should_have_underscores: true\n</content> <author-email-address>david@loudthinking.com</author-email-address> <parent-id></parent-id> <ad-revenue type="decimal">1.5</ad-revenue> <optimum-viewing-angle type="float">135</optimum-viewing-angle> - <resident type="symbol">yes</resident> </topic> EOT @@ -1033,12 +1031,10 @@ class HashToXmlTest < ActiveSupport::TestCase :replies_close_in => 2592000000, :written_on => Date.new(2003, 7, 16), :viewed_at => Time.utc(2003, 7, 16, 9, 28), - :content => { :message => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] }, :author_email_address => "david@loudthinking.com", :parent_id => nil, :ad_revenue => BigDecimal("1.50"), :optimum_viewing_angle => 135.0, - :resident => :yes }.stringify_keys assert_equal expected_topic_hash, Hash.from_xml(topic_xml)["topic"] @@ -1052,7 +1048,6 @@ class HashToXmlTest < ActiveSupport::TestCase <approved type="boolean"></approved> <written-on type="date"></written-on> <viewed-at type="datetime"></viewed-at> - <content type="yaml"></content> <parent-id></parent-id> </topic> EOT @@ -1063,7 +1058,6 @@ class HashToXmlTest < ActiveSupport::TestCase :approved => nil, :written_on => nil, :viewed_at => nil, - :content => nil, :parent_id => nil }.stringify_keys @@ -1290,6 +1284,28 @@ class HashToXmlTest < ActiveSupport::TestCase assert_equal expected_product_hash, Hash.from_xml(product_xml)["product"] end + def test_from_xml_raises_on_disallowed_type_attributes + assert_raise ActiveSupport::XMLConverter::DisallowedType do + Hash.from_xml '<product><name type="foo">value</name></product>', %w(foo) + end + end + + def test_from_xml_disallows_symbol_and_yaml_types_by_default + assert_raise ActiveSupport::XMLConverter::DisallowedType do + Hash.from_xml '<product><name type="symbol">value</name></product>' + end + + assert_raise ActiveSupport::XMLConverter::DisallowedType do + Hash.from_xml '<product><name type="yaml">value</name></product>' + end + end + + def test_from_trusted_xml_allows_symbol_and_yaml_types + expected = { 'product' => { 'name' => :value }} + assert_equal expected, Hash.from_trusted_xml('<product><name type="symbol">value</name></product>') + assert_equal expected, Hash.from_trusted_xml('<product><name type="yaml">:value</name></product>') + end + def test_should_use_default_value_for_unknown_key hash_wia = HashWithIndifferentAccess.new(3) assert_equal 3, hash_wia[:new_key] |