diff -up openssl-1.0.1e/crypto/asn1/a_d2i_fp.c.asn1-bio-dos openssl-1.0.1e/crypto/asn1/a_d2i_fp.c --- openssl-1.0.1e/crypto/asn1/a_d2i_fp.c.asn1-bio-dos 2013-02-11 16:02:47.000000000 +0100 +++ openssl-1.0.1e/crypto/asn1/a_d2i_fp.c 2016-04-29 13:44:52.205538739 +0200 @@ -139,6 +139,7 @@ void *ASN1_item_d2i_fp(const ASN1_ITEM * #endif #define HEADER_SIZE 8 +#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) { BUF_MEM *b; @@ -230,6 +231,8 @@ static int asn1_d2i_read_bio(BIO *in, BU want=c.slen; if (want > (len-off)) { + size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; + want-=(len-off); if (want > INT_MAX /* BIO_read takes an int length */ || len+want < len) @@ -237,24 +240,38 @@ static int asn1_d2i_read_bio(BIO *in, BU ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG); goto err; } - if (!BUF_MEM_grow_clean(b,len+want)) - { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE); - goto err; - } while (want > 0) { - i=BIO_read(in,&(b->data[len]),want); - if (i <= 0) + /* + * Read content in chunks of increasing size + * so we can return an error for EOF without + * having to allocate the entire content length + * in one go. + */ + size_t chunk = want > chunk_max ? chunk_max : want; + + if (!BUF_MEM_grow_clean(b, len + chunk)) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, - ASN1_R_NOT_ENOUGH_DATA); + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); goto err; } - /* This can't overflow because - * |len+want| didn't overflow. */ - len+=i; - want-=i; + want -= chunk; + while (chunk > 0) + { + i = BIO_read(in, &(b->data[len]), chunk); + if (i <= 0) + { + ASN1err(ASN1_F_ASN1_D2I_READ_BIO, + ASN1_R_NOT_ENOUGH_DATA); + goto err; + } + /* This can't overflow because + * |len+want| didn't overflow. */ + len += i; + chunk -= i; + } + if (chunk_max < INT_MAX/2) + chunk_max *= 2; } } if (off + c.slen < off)