Sophie

Sophie

distrib > Mageia > 5 > i586 > media > core-updates-src > by-pkgid > 72359a4accb612af93f2f9dc19bf7a74 > files > 12

ruby-2.0.0.p648-1.6.mga5.src.rpm

diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 6d564a312f35..719063c551e5 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -871,19 +871,18 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
 {
     VALUE value, asn1data, ary;
     int infinite;
-    long off = *offset;
+    long available_len, off = *offset;
 
     infinite = (j == 0x21);
     ary = rb_ary_new();
 
-    while (length > 0 || infinite) {
+    available_len = infinite ? max_len : length;
+    while (available_len > 0) {
 	long inner_read = 0;
-	value = ossl_asn1_decode0(pp, max_len, &off, depth + 1, yield, &inner_read);
+	value = ossl_asn1_decode0(pp, available_len, &off, depth + 1, yield, &inner_read);
 	*num_read += inner_read;
-	max_len -= inner_read;
+	available_len -= inner_read;
 	rb_ary_push(ary, value);
-	if (length > 0)
-	    length -= inner_read;
 
 	if (infinite &&
 	    NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC &&
@@ -974,7 +973,7 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
     if(j & V_ASN1_CONSTRUCTED) {
 	*pp += hlen;
 	off += hlen;
-	asn1data = int_ossl_asn1_decode0_cons(pp, length, len, &off, depth, yield, j, tag, tag_class, &inner_read);
+	asn1data = int_ossl_asn1_decode0_cons(pp, length - hlen, len, &off, depth, yield, j, tag, tag_class, &inner_read);
 	inner_read += hlen;
     }
     else {
diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb
index 9fb5a551c66d..a6d7c2c14e00 100644
--- a/test/openssl/test_asn1.rb
+++ b/test/openssl/test_asn1.rb
@@ -595,6 +595,29 @@ def test_recursive_octet_string_parse
     assert_equal(false, asn1.value[3].infinite_length)
   end
 
+  def test_decode_constructed_overread
+    test = %w{ 31 06 31 02 30 02 05 00 }
+    #                          ^ <- invalid
+    raw = [test.join].pack("H*")
+    ret = []
+    assert_raise(OpenSSL::ASN1::ASN1Error) {
+      OpenSSL::ASN1.traverse(raw) { |x| ret << x }
+    }
+    assert_equal 2, ret.size
+    assert_equal 17, ret[0][6]
+    assert_equal 17, ret[1][6]
+
+    test = %w{ 31 80 30 03 00 00 }
+    #                    ^ <- invalid
+    raw = [test.join].pack("H*")
+    ret = []
+    assert_raise(OpenSSL::ASN1::ASN1Error) {
+      OpenSSL::ASN1.traverse(raw) { |x| ret << x }
+    }
+    assert_equal 1, ret.size
+    assert_equal 17, ret[0][6]
+  end
+
   private
 
   def assert_universal(tag, asn1)