aboutsummaryrefslogtreecommitdiffstats
path: root/ext
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-09-19 15:38:44 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-09-28 12:15:14 +0900
commit1648afef33c1d97fb203c82291b8a61269e85d3b (patch)
treee6b4315a8aeed890a366cd692ea88b8a9432a68f /ext
parentc3da84ff9af57dc61dff84a64fc01eefdbe21ceb (diff)
downloadruby-openssl-1648afef33c1d97fb203c82291b8a61269e85d3b.tar.gz
asn1: fix out-of-bounds read in decoding constructed objectstopic/asn1-fix-oob-read-constructed
OpenSSL::ASN1.{decode,decode_all,traverse} have a bug of out-of-bounds read. int_ossl_asn1_decode0_cons() does not give the correct available length to ossl_asn1_decode() when decoding the inner components of a constructed object. This can cause out-of-bounds read if a crafted input given. Reference: https://hackerone.com/reports/170316
Diffstat (limited to 'ext')
-rw-r--r--ext/openssl/ossl_asn1.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 2b8a85f0..90d35c6d 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -832,19 +832,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 &&
@@ -935,7 +934,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 {