[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#700524: marked as done (unblock: ruby1.9.1/1.9.3.194-7)



Your message dated Wed, 13 Feb 2013 21:36:47 +0000
with message-id <1360791407.9953.9.camel@jacala.jungle.funky-badger.org>
and subject line Re: Bug#700524: unblock: ruby1.9.1/1.9.3.194-7
has caused the Debian Bug report #700524,
regarding unblock: ruby1.9.1/1.9.3.194-7
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
700524: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=700524
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package ruby1.9.1

The package ruby1.9.1 (version: 1.9.3.194-5) currently in testing ships
a version of the ruby JSON library suffering from CVE-2013-0269, which
can cause denial of service and unsafe object creations. This is
described in bug report #700471.

I adapted the patch provided upstream
https://github.com/ruby/ruby/commit/e9e9ec43f5f601782fe841d7364723d6e4975fa7
to fix this issue, and in coordination with Antonio Terceiro, one of the
maintainers of the package, I uploaded to unstable a new version of
ruby1.9.1 with that tested fix.

This upload replaces in unstable version 1.9.3.194-6, uploaded to unstable
yesterday, and already unblocked (#700455).

I am attaching the debdiff against that previous unblocked version.

Thanks!

Cédric


unblock ruby1.9.1/1.9.3.194-7

-- System Information:
Debian Release: 7.0
  APT prefers unstable
  APT policy: (990, 'unstable'), (500, 'testing'), (150, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.7-trunk-amd64 (SMP w/4 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff -Nru ruby1.9.1-1.9.3.194/debian/changelog ruby1.9.1-1.9.3.194/debian/changelog
--- ruby1.9.1-1.9.3.194/debian/changelog	2013-02-12 20:04:22.000000000 +0100
+++ ruby1.9.1-1.9.3.194/debian/changelog	2013-02-13 16:30:04.000000000 +0100
@@ -1,3 +1,10 @@
+ruby1.9.1 (1.9.3.194-7) unstable; urgency=high
+
+  * debian/patches/CVE-2013-0269.patch: fix possible denial of service and
+    unsafe object creation vulnerability in JSON (Closes: #700471)
+
+ -- Cédric Boutillier <boutil@debian.org>  Wed, 13 Feb 2013 14:56:19 +0100
+
 ruby1.9.1 (1.9.3.194-6) unstable; urgency=high
 
   [Nobuhiro Iwamatsu]
diff -Nru ruby1.9.1-1.9.3.194/debian/patches/CVE-2013-0269.patch ruby1.9.1-1.9.3.194/debian/patches/CVE-2013-0269.patch
--- ruby1.9.1-1.9.3.194/debian/patches/CVE-2013-0269.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby1.9.1-1.9.3.194/debian/patches/CVE-2013-0269.patch	2013-02-13 16:02:56.000000000 +0100
@@ -0,0 +1,430 @@
+Description: fix denial of service and unsafe object creation
+ vulnerability in JSON. [CVE-2013-0269]
+From: NAKAMURA Usaku  <usa@ruby-lang.org>
+Origin: https://github.com/ruby/ruby/commit/e9e9ec43f5f601782fe841d7364723d6e4975fa7
+Reviewed-by: Cédric Boutillier <boutil@debian.org>
+Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=700471
+Last-Update: 2013-02-13
+
+--- a/ext/json/lib/json/add/core.rb
++++ b/ext/json/lib/json/add/core.rb
+@@ -36,8 +36,8 @@
+     if usec = object.delete('u') # used to be tv_usec -> tv_nsec
+       object['n'] = usec * 1000
+     end
+-    if respond_to?(:tv_nsec)
+-      at(*object.values_at('s', 'n'))
++    if instance_methods.include?(:tv_nsec)
++      at(object['s'], Rational(object['n'], 1000))
+     else
+       at(object['s'], object['n'] / 1000)
+     end
+@@ -46,10 +46,13 @@
+   # Returns a hash, that will be turned into a JSON object and represent this
+   # object.
+   def as_json(*)
++    nanoseconds = [ tv_usec * 1000 ]
++    respond_to?(:tv_nsec) and nanoseconds << tv_nsec
++    nanoseconds = nanoseconds.max
+     {
+       JSON.create_id => self.class.name,
+       's'            => tv_sec,
+-      'n'            => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
++      'n'            => nanoseconds,
+     }
+   end
+ 
+--- a/ext/json/lib/json/common.rb
++++ b/ext/json/lib/json/common.rb
+@@ -141,7 +141,7 @@
+   #   the default.
+   # * *create_additions*: If set to false, the Parser doesn't create
+   #   additions even if a matching class and create_id was found. This option
+-  #   defaults to true.
++  #   defaults to false.
+   # * *object_class*: Defaults to Hash
+   # * *array_class*: Defaults to Array
+   def parse(source, opts = {})
+@@ -162,7 +162,7 @@
+   #   to true.
+   # * *create_additions*: If set to false, the Parser doesn't create
+   #   additions even if a matching class and create_id was found. This option
+-  #   defaults to true.
++  #   defaults to false.
+   def parse!(source, opts = {})
+     opts = {
+       :max_nesting  => false,
+@@ -287,11 +287,18 @@
+   # Load a ruby data structure from a JSON _source_ and return it. A source can
+   # either be a string-like object, an IO-like object, or an object responding
+   # to the read method. If _proc_ was given, it will be called with any nested
+-  # Ruby object as an argument recursively in depth first order.
++  # Ruby object as an argument recursively in depth first order. To modify the
++  # default options pass in the optional _options_ argument as well.
+   #
+   # This method is part of the implementation of the load/dump interface of
+   # Marshal and YAML.
+-  def load(source, proc = nil)
++  def load(source, proc = nil, options = {})
++    load_default_options = {
++      :max_nesting      => false,
++      :allow_nan        => true,
++      :create_additions => false
++    }
++    opts = load_default_options.merge options
+     if source.respond_to? :to_str
+       source = source.to_str
+     elsif source.respond_to? :to_io
+@@ -299,7 +306,7 @@
+     else
+       source = source.read
+     end
+-    result = parse(source, :max_nesting => false, :allow_nan => true)
++    result = parse(source, opts)
+     recurse_proc(result, &proc) if proc
+     result
+   end
+--- a/ext/json/parser/parser.c
++++ b/ext/json/parser/parser.c
+@@ -1676,7 +1676,7 @@
+             if (option_given_p(opts, tmp)) {
+                 json->create_additions = RTEST(rb_hash_aref(opts, tmp));
+             } else {
+-                json->create_additions = 1;
++                json->create_additions = 0;
+             }
+             tmp = ID2SYM(i_create_id);
+             if (option_given_p(opts, tmp)) {
+@@ -1723,7 +1723,7 @@
+ }
+ 
+ 
+-#line 1719 "parser.c"
++#line 1722 "parser.c"
+ static const int JSON_start = 1;
+ static const int JSON_first_final = 10;
+ static const int JSON_error = 0;
+@@ -1731,7 +1731,7 @@
+ static const int JSON_en_main = 1;
+ 
+ 
+-#line 726 "parser.rl"
++#line 729 "parser.rl"
+ 
+ 
+ static VALUE cParser_parse_strict(VALUE self)
+@@ -1742,16 +1742,16 @@
+     GET_PARSER;
+ 
+ 
+-#line 1738 "parser.c"
++#line 1741 "parser.c"
+ 	{
+ 	cs = JSON_start;
+ 	}
+ 
+-#line 736 "parser.rl"
++#line 739 "parser.rl"
+     p = json->source;
+     pe = p + json->len;
+ 
+-#line 1747 "parser.c"
++#line 1750 "parser.c"
+ 	{
+ 	if ( p == pe )
+ 		goto _test_eof;
+@@ -1807,7 +1807,7 @@
+ 		goto st1;
+ 	goto st5;
+ tr3:
+-#line 715 "parser.rl"
++#line 718 "parser.rl"
+ 	{
+         char *np;
+         json->current_nesting = 1;
+@@ -1816,7 +1816,7 @@
+     }
+ 	goto st10;
+ tr4:
+-#line 708 "parser.rl"
++#line 711 "parser.rl"
+ 	{
+         char *np;
+         json->current_nesting = 1;
+@@ -1828,7 +1828,7 @@
+ 	if ( ++p == pe )
+ 		goto _test_eof10;
+ case 10:
+-#line 1824 "parser.c"
++#line 1827 "parser.c"
+ 	switch( (*p) ) {
+ 		case 13: goto st10;
+ 		case 32: goto st10;
+@@ -1885,7 +1885,7 @@
+ 	_out: {}
+ 	}
+ 
+-#line 739 "parser.rl"
++#line 742 "parser.rl"
+ 
+     if (cs >= JSON_first_final && p == pe) {
+         return result;
+@@ -1897,7 +1897,7 @@
+ 
+ 
+ 
+-#line 1893 "parser.c"
++#line 1896 "parser.c"
+ static const int JSON_quirks_mode_start = 1;
+ static const int JSON_quirks_mode_first_final = 10;
+ static const int JSON_quirks_mode_error = 0;
+@@ -1905,7 +1905,7 @@
+ static const int JSON_quirks_mode_en_main = 1;
+ 
+ 
+-#line 764 "parser.rl"
++#line 767 "parser.rl"
+ 
+ 
+ static VALUE cParser_parse_quirks_mode(VALUE self)
+@@ -1916,16 +1916,16 @@
+     GET_PARSER;
+ 
+ 
+-#line 1912 "parser.c"
++#line 1915 "parser.c"
+ 	{
+ 	cs = JSON_quirks_mode_start;
+ 	}
+ 
+-#line 774 "parser.rl"
++#line 777 "parser.rl"
+     p = json->source;
+     pe = p + json->len;
+ 
+-#line 1921 "parser.c"
++#line 1924 "parser.c"
+ 	{
+ 	if ( p == pe )
+ 		goto _test_eof;
+@@ -1959,7 +1959,7 @@
+ cs = 0;
+ 	goto _out;
+ tr2:
+-#line 756 "parser.rl"
++#line 759 "parser.rl"
+ 	{
+         char *np = JSON_parse_value(json, p, pe, &result);
+         if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
+@@ -1969,7 +1969,7 @@
+ 	if ( ++p == pe )
+ 		goto _test_eof10;
+ case 10:
+-#line 1965 "parser.c"
++#line 1968 "parser.c"
+ 	switch( (*p) ) {
+ 		case 13: goto st10;
+ 		case 32: goto st10;
+@@ -2058,7 +2058,7 @@
+ 	_out: {}
+ 	}
+ 
+-#line 777 "parser.rl"
++#line 780 "parser.rl"
+ 
+     if (cs >= JSON_quirks_mode_first_final && p == pe) {
+         return result;
+--- a/ext/json/parser/parser.rl
++++ b/ext/json/parser/parser.rl
+@@ -607,6 +607,9 @@
+  *   defaults to true.
+  * * *object_class*: Defaults to Hash
+  * * *array_class*: Defaults to Array
++ * * *quirks_mode*: Enables quirks_mode for parser, that is for example
++ *   parsing single JSON values instead of documents is possible.
++ *
+  */
+ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ {
+@@ -657,7 +660,7 @@
+             if (option_given_p(opts, tmp)) {
+                 json->create_additions = RTEST(rb_hash_aref(opts, tmp));
+             } else {
+-                json->create_additions = 1;
++                json->create_additions = 0;
+             }
+             tmp = ID2SYM(i_create_id);
+             if (option_given_p(opts, tmp)) {
+--- a/test/json/test_json.rb
++++ b/test/json/test_json.rb
+@@ -4,6 +4,7 @@
+ require 'test/unit'
+ require File.join(File.dirname(__FILE__), 'setup_variant')
+ require 'stringio'
++require 'tempfile'
+ 
+ unless Array.method_defined?(:permutation)
+   begin
+@@ -263,12 +264,12 @@
+   def test_generation_of_core_subclasses_with_new_to_json
+     obj = SubHash2["foo" => SubHash2["bar" => true]]
+     obj_json = JSON(obj)
+-    obj_again = JSON(obj_json)
++    obj_again = JSON.parse(obj_json, :create_additions => true)
+     assert_kind_of SubHash2, obj_again
+     assert_kind_of SubHash2, obj_again['foo']
+     assert obj_again['foo']['bar']
+     assert_equal obj, obj_again
+-    assert_equal ["foo"], JSON(JSON(SubArray2["foo"]))
++    assert_equal ["foo"], JSON(JSON(SubArray2["foo"]), :create_additions => true)
+   end
+ 
+   def test_generation_of_core_subclasses_with_default_to_json
+@@ -414,6 +415,25 @@
+       JSON.parse('{"foo":"bar", "baz":"quux"}', :symbolize_names => true))
+   end
+ 
++  def test_load
++    assert_equal @hash, JSON.load(@json)
++    tempfile = Tempfile.open('json')
++    tempfile.write @json
++    tempfile.rewind
++    assert_equal @hash, JSON.load(tempfile)
++    stringio = StringIO.new(@json)
++    stringio.rewind
++    assert_equal @hash, JSON.load(stringio)
++    assert_raise(NoMethodError) { JSON.load(nil) }
++    assert_raise(JSON::ParserError) {JSON.load('') }
++  end
++
++  def test_load_with_options
++    small_hash  = JSON("foo" => 'bar')
++    symbol_hash = { :foo => 'bar' }
++    assert_equal symbol_hash, JSON.load(small_hash, nil, :symbolize_names => true)
++  end
++
+   def test_load_dump
+     too_deep = '[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]'
+     assert_equal too_deep, JSON.dump(eval(too_deep))
+--- a/test/json/test_json_addition.rb
++++ b/test/json/test_json_addition.rb
+@@ -69,11 +69,19 @@
+     a = A.new(666)
+     assert A.json_creatable?
+     json = generate(a)
+-    a_again = JSON.parse(json)
++    a_again = JSON.parse(json, :create_additions => true)
+     assert_kind_of a.class, a_again
+     assert_equal a, a_again
+   end
+ 
++  def test_extended_json_default
++    a = A.new(666)
++    assert A.json_creatable?
++    json = generate(a)
++    a_hash = JSON.parse(json)
++    assert_kind_of Hash, a_hash
++  end
++
+   def test_extended_json_disabled
+     a = A.new(666)
+     assert A.json_creatable?
+@@ -100,7 +108,7 @@
+     c = C.new
+     assert !C.json_creatable?
+     json = generate(c)
+-    assert_raises(ArgumentError, NameError) { JSON.parse(json) }
++    assert_raises(ArgumentError, NameError) { JSON.parse(json, :create_additions => true) }
+   end
+ 
+   def test_raw_strings
+@@ -118,7 +126,7 @@
+     assert_match(/\A\{.*\}\Z/, json)
+     assert_match(/"json_class":"String"/, json)
+     assert_match(/"raw":\[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255\]/, json)
+-    raw_again = JSON.parse(json)
++    raw_again = JSON.parse(json, :create_additions => true)
+     assert_equal raw, raw_again
+   end
+ 
+@@ -126,17 +134,17 @@
+ 
+   def test_core
+     t = Time.now
+-    assert_equal t.inspect, JSON(JSON(t)).inspect
++    assert_equal t, JSON(JSON(t), :create_additions => true)
+     d = Date.today
+-    assert_equal d, JSON(JSON(d))
++    assert_equal d, JSON(JSON(d), :create_additions => true)
+     d = DateTime.civil(2007, 6, 14, 14, 57, 10, Rational(1, 12), 2299161)
+-    assert_equal d, JSON(JSON(d))
+-    assert_equal 1..10, JSON(JSON(1..10))
+-    assert_equal 1...10, JSON(JSON(1...10))
+-    assert_equal "a".."c", JSON(JSON("a".."c"))
+-    assert_equal "a"..."c", JSON(JSON("a"..."c"))
++    assert_equal d, JSON(JSON(d), :create_additions => true)
++    assert_equal 1..10, JSON(JSON(1..10), :create_additions => true)
++    assert_equal 1...10, JSON(JSON(1...10), :create_additions => true)
++    assert_equal "a".."c", JSON(JSON("a".."c"), :create_additions => true)
++    assert_equal "a"..."c", JSON(JSON("a"..."c"), :create_additions => true)
+     s = MyJsonStruct.new 4711, 'foot'
+-    assert_equal s, JSON(JSON(s))
++    assert_equal s, JSON(JSON(s), :create_additions => true)
+     struct = Struct.new :foo, :bar
+     s = struct.new 4711, 'foot'
+     assert_raises(JSONError) { JSON(s) }
+@@ -144,24 +152,24 @@
+       raise TypeError, "test me"
+     rescue TypeError => e
+       e_json = JSON.generate e
+-      e_again = JSON e_json
++      e_again = JSON e_json, :create_additions => true
+       assert_kind_of TypeError, e_again
+       assert_equal e.message, e_again.message
+       assert_equal e.backtrace, e_again.backtrace
+     end
+-    assert_equal(/foo/, JSON(JSON(/foo/)))
+-    assert_equal(/foo/i, JSON(JSON(/foo/i)))
++    assert_equal(/foo/, JSON(JSON(/foo/), :create_additions => true))
++    assert_equal(/foo/i, JSON(JSON(/foo/i), :create_additions => true))
+   end
+ 
+   def test_utc_datetime
+     now = Time.now
+-    d = DateTime.parse(now.to_s)                    # usual case
+-    assert_equal d, JSON.parse(d.to_json)
++    d = DateTime.parse(now.to_s, :create_additions => true)                    # usual case
++    assert_equal d, JSON.parse(d.to_json, :create_additions => true)
+     d = DateTime.parse(now.utc.to_s)                # of = 0
+-    assert_equal d, JSON.parse(d.to_json)
++    assert_equal d, JSON.parse(d.to_json, :create_additions => true)
+     d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(1,24))
+-    assert_equal d, JSON.parse(d.to_json)
++    assert_equal d, JSON.parse(d.to_json, :create_additions => true)
+     d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(12,24))
+-    assert_equal d, JSON.parse(d.to_json)
++    assert_equal d, JSON.parse(d.to_json, :create_additions => true)
+   end
+ end
+--- a/test/json/test_json_string_matching.rb
++++ b/test/json/test_json_string_matching.rb
+@@ -27,14 +27,13 @@
+     t = TestTime.new
+     t_json = [ t ].to_json
+     assert_equal [ t ],
+-      JSON.parse(t_json,
+-        :match_string => { /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4}\Z/ => TestTime })
++      JSON.parse(t_json, :create_additions => true,
++        :match_string => { /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4}\z/ => TestTime })
+     assert_equal [ t.strftime('%FT%T%z') ],
+-      JSON.parse(t_json,
+-        :match_string => { /\A\d{3}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4}\Z/ => TestTime })
++      JSON.parse(t_json, :create_additions => true,
++        :match_string => { /\A\d{3}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4}\z/ => TestTime })
+     assert_equal [ t.strftime('%FT%T%z') ],
+       JSON.parse(t_json,
+-        :match_string => { /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4}\Z/ => TestTime },
+-        :create_additions => false)
++        :match_string => { /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4}\z/ => TestTime })
+   end
+ end
diff -Nru ruby1.9.1-1.9.3.194/debian/patches/series ruby1.9.1-1.9.3.194/debian/patches/series
--- ruby1.9.1-1.9.3.194/debian/patches/series	2013-02-12 20:04:22.000000000 +0100
+++ ruby1.9.1-1.9.3.194/debian/patches/series	2013-02-13 14:56:11.000000000 +0100
@@ -20,3 +20,4 @@
 CVE-2012-4522.patch
 20121120-cve-2012-5371.diff
 CVE-2013-0256.patch
+CVE-2013-0269.patch

Attachment: signature.asc
Description: Digital signature


--- End Message ---
--- Begin Message ---
On Wed, 2013-02-13 at 22:28 +0100, Cédric Boutillier wrote:
> The package ruby1.9.1 (version: 1.9.3.194-5) currently in testing ships
> a version of the ruby JSON library suffering from CVE-2013-0269, which
> can cause denial of service and unsafe object creations. This is
> described in bug report #700471.
[...]
> This upload replaces in unstable version 1.9.3.194-6, uploaded to unstable
> yesterday, and already unblocked (#700455).

I updated the earlier unblock a little earlier; thanks.

Regards,

Adam

--- End Message ---

Reply to: