@ -57,6 +57,7 @@
*/
*/
# include <stdio.h>
# include <stdio.h>
# include <limits.h>
# include "cryptlib.h"
# include "cryptlib.h"
# include <openssl/buffer.h>
# include <openssl/buffer.h>
# include <openssl/asn1_mac.h>
# include <openssl/asn1_mac.h>
@ -143,17 +144,11 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
BUF_MEM * b ;
BUF_MEM * b ;
unsigned char * p ;
unsigned char * p ;
int i ;
int i ;
int ret = - 1 ;
ASN1_const_CTX c ;
ASN1_const_CTX c ;
in t want = HEADER_SIZE ;
size_ t want = HEADER_SIZE ;
int eos = 0 ;
int eos = 0 ;
# if defined(__GNUC__) && defined(__ia64)
size_t off = 0 ;
/* pathetic compiler bug in all known versions as of Nov. 2002 */
size_t len = 0 ;
long off = 0 ;
# else
int off = 0 ;
# endif
int len = 0 ;
b = BUF_MEM_new ( ) ;
b = BUF_MEM_new ( ) ;
if ( b = = NULL )
if ( b = = NULL )
@ -169,7 +164,7 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
{
want - = ( len - off ) ;
want - = ( len - off ) ;
if ( ! BUF_MEM_grow_clean ( b , len + want ) )
if ( len + want < len | | ! BUF_MEM_grow_clean ( b , len + want ) )
{
{
ASN1err ( ASN1_F_ASN1_D2I_READ_BIO , ERR_R_MALLOC_FAILURE ) ;
ASN1err ( ASN1_F_ASN1_D2I_READ_BIO , ERR_R_MALLOC_FAILURE ) ;
goto err ;
goto err ;
@ -181,7 +176,14 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
goto err ;
goto err ;
}
}
if ( i > 0 )
if ( i > 0 )
{
if ( len + i < len )
{
ASN1err ( ASN1_F_ASN1_D2I_READ_BIO , ASN1_R_TOO_LONG ) ;
goto err ;
}
len + = i ;
len + = i ;
}
}
}
/* else data already loaded */
/* else data already loaded */
@ -206,6 +208,11 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
{
/* no data body so go round again */
/* no data body so go round again */
eos + + ;
eos + + ;
if ( eos < 0 )
{
ASN1err ( ASN1_F_ASN1_D2I_READ_BIO , ASN1_R_HEADER_TOO_LONG ) ;
goto err ;
}
want = HEADER_SIZE ;
want = HEADER_SIZE ;
}
}
else if ( eos & & ( c . slen = = 0 ) & & ( c . tag = = V_ASN1_EOC ) )
else if ( eos & & ( c . slen = = 0 ) & & ( c . tag = = V_ASN1_EOC ) )
@ -220,10 +227,16 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
else
else
{
{
/* suck in c.slen bytes of data */
/* suck in c.slen bytes of data */
want = ( int ) c . slen ;
want = c . slen ;
if ( want > ( len - off ) )
if ( want > ( len - off ) )
{
{
want - = ( len - off ) ;
want - = ( len - off ) ;
if ( want > INT_MAX /* BIO_read takes an int length */ | |
len + want < len )
{
ASN1err ( ASN1_F_ASN1_D2I_READ_BIO , ASN1_R_TOO_LONG ) ;
goto err ;
}
if ( ! BUF_MEM_grow_clean ( b , len + want ) )
if ( ! BUF_MEM_grow_clean ( b , len + want ) )
{
{
ASN1err ( ASN1_F_ASN1_D2I_READ_BIO , ERR_R_MALLOC_FAILURE ) ;
ASN1err ( ASN1_F_ASN1_D2I_READ_BIO , ERR_R_MALLOC_FAILURE ) ;
@ -238,11 +251,18 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
ASN1_R_NOT_ENOUGH_DATA ) ;
ASN1_R_NOT_ENOUGH_DATA ) ;
goto err ;
goto err ;
}
}
/* This can't overflow because
* | len + want | didn ' t overflow . */
len + = i ;
len + = i ;
want - = i ;
want - = i ;
}
}
}
}
off + = ( int ) c . slen ;
if ( off + c . slen < off )
{
ASN1err ( ASN1_F_ASN1_D2I_READ_BIO , ASN1_R_TOO_LONG ) ;
goto err ;
}
off + = c . slen ;
if ( eos < = 0 )
if ( eos < = 0 )
{
{
break ;
break ;
@ -252,9 +272,15 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
}
}
}
}
if ( off > INT_MAX )
{
ASN1err ( ASN1_F_ASN1_D2I_READ_BIO , ASN1_R_TOO_LONG ) ;
goto err ;
}
* pb = b ;
* pb = b ;
return off ;
return off ;
err :
err :
if ( b ! = NULL ) BUF_MEM_free ( b ) ;
if ( b ! = NULL ) BUF_MEM_free ( b ) ;
return ( ret ) ;
return - 1 ;
}
}