Fix ASAN crash spotted after r_str_ndup refactoring in x509 (#18481)

* Reproducer: r2 SEGV-a94-0b5-0a6
This commit is contained in:
pancake 2021-03-18 02:21:00 +01:00 committed by GitHub
parent dac5c3850e
commit 2b8671012f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 35 deletions

View File

@ -12,13 +12,13 @@ R_API void asn1_setformat (int fmt) {
ASN1_STD_FORMAT = fmt;
}
static ut32 asn1_ber_indefinite (const ut8 *buffer, ut32 length) {
static ut32 asn1_ber_indefinite(const ut8 *buffer, ut32 length) {
if (!buffer || length < 3) {
return 0;
}
const ut8* next = buffer + 2;
const ut8* end = buffer + (length - 3);
while (next < end) {
const ut8* end = buffer + length - 3;
while (next + 1 < end) {
if (!next[0] && !next[1]) {
break;
}
@ -30,15 +30,15 @@ static ut32 asn1_ber_indefinite (const ut8 *buffer, ut32 length) {
}
next += sz;
}
next ++;
next++;
}
return (next - buffer) + 2;
}
static RASN1Object *asn1_parse_header (const ut8 *buffer, ut32 length, const ut8 *start_pointer) {
static RASN1Object *asn1_parse_header(const ut8 *buffer, ut32 length, const ut8 *start_pointer) {
ut8 head, length8, byte;
ut64 length64;
if (!buffer || length < 2) {
if (!buffer || length < 3) {
return NULL;
}
@ -69,6 +69,9 @@ static RASN1Object *asn1_parse_header (const ut8 *buffer, ut32 length, const ut8
}
object->sector += length8;
} else {
if (length < 3) {
goto out_error;
}
length64 = asn1_ber_indefinite (object->sector, length - 2);
}
object->length = (ut32) length64;
@ -93,7 +96,7 @@ out_error:
return NULL;
}
static ut32 r_asn1_count_objects (const ut8 *buffer, ut32 length) {
static ut32 r_asn1_count_objects(const ut8 *buffer, ut32 length) {
if (!buffer || !length) {
return 0;
}
@ -116,7 +119,7 @@ static ut32 r_asn1_count_objects (const ut8 *buffer, ut32 length) {
return counter;
}
R_API RASN1Object *r_asn1_create_object (const ut8 *buffer, ut32 length, const ut8 *start_pointer) {
R_API RASN1Object *r_asn1_create_object(const ut8 *buffer, ut32 length, const ut8 *start_pointer) {
RASN1Object *object = asn1_parse_header (buffer, length, start_pointer);
if (object && (object->form == FORM_CONSTRUCTED || object->tag == TAG_BITSTRING || object->tag == TAG_OCTETSTRING)) {
const ut8 *next = object->sector;

View File

@ -50,16 +50,17 @@ R_API RASN1String *r_asn1_concatenate_strings (RASN1String *s0, RASN1String *s1,
return res;
}
R_API RASN1String *r_asn1_stringify_string (const ut8 *buffer, ut32 length) {
if (!buffer || !length) {
R_API RASN1String *r_asn1_stringify_string(const ut8 *buffer, ut32 length) {
if (!buffer || length < 1) {
return NULL;
}
char *str = r_str_ndup ((const char *)buffer, length);
if (!str) {
return NULL;
}
r_str_filter (str, length);
return r_asn1_create_string (str, true, length);
int str_len = strlen (str);
r_str_filter (str, str_len);
return r_asn1_create_string (str, true, str_len);
}
R_API RASN1String *r_asn1_stringify_utctime (const ut8 *buffer, ut32 length) {
@ -103,7 +104,7 @@ R_API RASN1String *r_asn1_stringify_utctime (const ut8 *buffer, ut32 length) {
return asn1str;
}
R_API RASN1String *r_asn1_stringify_time (const ut8 *buffer, ut32 length) {
R_API RASN1String *r_asn1_stringify_time(const ut8 *buffer, ut32 length) {
if (!buffer || length != 15 || buffer[14] != 'Z') {
return NULL;
}
@ -208,7 +209,7 @@ R_API RASN1String *r_asn1_stringify_integer (const ut8 *buffer, ut32 length) {
return asn1str;
}
R_API RASN1String* r_asn1_stringify_bytes (const ut8 *buffer, ut32 length) {
R_API RASN1String* r_asn1_stringify_bytes(const ut8 *buffer, ut32 length) {
ut32 i, j, k;
ut64 size;
ut8 c;
@ -308,7 +309,7 @@ R_API RASN1String *r_asn1_stringify_oid (const ut8* buffer, ut32 length) {
return asn1str;
}
R_API void r_asn1_free_string (RASN1String* str) {
R_API void r_asn1_free_string(RASN1String* str) {
if (str) {
if (str->allocated) {
free ((char*) str->string);
@ -317,7 +318,7 @@ R_API void r_asn1_free_string (RASN1String* str) {
}
}
R_API RASN1String *asn1_stringify_tag (RASN1Object *object) {
R_API RASN1String *asn1_stringify_tag(RASN1Object *object) {
if (!object) {
return NULL;
}
@ -355,7 +356,7 @@ R_API RASN1String *asn1_stringify_tag (RASN1Object *object) {
return newstr (s);
}
R_API RASN1String *asn1_stringify_sector (RASN1Object *object) {
R_API RASN1String *asn1_stringify_sector(RASN1Object *object) {
if (!object) {
return NULL;
}

View File

@ -137,7 +137,7 @@ static void r_pkcs7_free_contentinfo(RPKCS7ContentInfo *ci) {
}
static bool r_pkcs7_parse_issuerandserialnumber(RPKCS7IssuerAndSerialNumber *iasu, RASN1Object *object) {
if (!iasu || !object || object->list.length != 2) {
if (!iasu || !object || object->list.length < 2) {
return false;
}
r_x509_parse_name (&iasu->issuer, object->list.objects[0]);

View File

@ -1,4 +1,4 @@
/* radare2 - LGPL - Copyright 2017-2018 - wargio */
/* radare2 - LGPL - Copyright 2017-2021 - wargio */
#include <r_util.h>
#include <r_cons.h>
@ -75,7 +75,7 @@ bool r_x509_parse_subjectpublickeyinfo (RX509SubjectPublicKeyInfo *spki, RASN1Ob
return true;
}
bool r_x509_parse_name (RX509Name *name, RASN1Object *object) {
R_API bool r_x509_parse_name(RX509Name *name, RASN1Object *object) {
ut32 i;
if (!name || !object || !object->list.length) {
return false;
@ -118,9 +118,9 @@ bool r_x509_parse_name (RX509Name *name, RASN1Object *object) {
return true;
}
bool r_x509_parse_extension (RX509Extension *ext, RASN1Object *object) {
R_API bool r_x509_parse_extension(RX509Extension *ext, RASN1Object *object) {
RASN1Object *o;
if (!ext || !object || object->list.length < 2) {
if (!ext || !object || object->list.length != 2) {
return false;
}
o = object->list.objects[0];
@ -139,7 +139,7 @@ bool r_x509_parse_extension (RX509Extension *ext, RASN1Object *object) {
return true;
}
bool r_x509_parse_extensions (RX509Extensions *ext, RASN1Object *object) {
R_API bool r_x509_parse_extensions(RX509Extensions *ext, RASN1Object *object) {
ut32 i;
if (!ext || !object || object->list.length != 1 || !object->list.objects[0]->length) {
return false;
@ -160,7 +160,7 @@ bool r_x509_parse_extensions (RX509Extensions *ext, RASN1Object *object) {
return true;
}
bool r_x509_parse_tbscertificate (RX509TBSCertificate *tbsc, RASN1Object *object) {
R_API bool r_x509_parse_tbscertificate (RX509TBSCertificate *tbsc, RASN1Object *object) {
RASN1Object **elems;
ut32 i;
ut32 shift = 0;
@ -213,7 +213,7 @@ bool r_x509_parse_tbscertificate (RX509TBSCertificate *tbsc, RASN1Object *object
return true;
}
RX509Certificate *r_x509_parse_certificate (RASN1Object *object) {
R_API RX509Certificate *r_x509_parse_certificate(RASN1Object *object) {
if (!object) {
return NULL;
}
@ -245,7 +245,7 @@ fail:
return cert;
}
RX509Certificate *r_x509_parse_certificate2 (const ut8 *buffer, ut32 length) {
R_API RX509Certificate *r_x509_parse_certificate2(const ut8 *buffer, ut32 length) {
RX509Certificate *certificate;
RASN1Object *object;
if (!buffer || !length) {
@ -257,7 +257,7 @@ RX509Certificate *r_x509_parse_certificate2 (const ut8 *buffer, ut32 length) {
return certificate;
}
RX509CRLEntry *r_x509_parse_crlentry (RASN1Object *object) {
R_API RX509CRLEntry *r_x509_parse_crlentry(RASN1Object *object) {
RX509CRLEntry *entry;
if (!object || object->list.length != 2) {
return NULL;
@ -272,17 +272,14 @@ RX509CRLEntry *r_x509_parse_crlentry (RASN1Object *object) {
}
R_API RX509CertificateRevocationList *r_x509_parse_crl(RASN1Object *object) {
RX509CertificateRevocationList *crl;
RASN1Object **elems;
if (!object || object->list.length < 4) {
return NULL;
}
crl = (RX509CertificateRevocationList *)malloc (sizeof (RX509CertificateRevocationList));
RX509CertificateRevocationList *crl = R_NEW0 (RX509CertificateRevocationList);
if (!crl) {
return NULL;
}
memset (crl, 0, sizeof (RX509CertificateRevocationList));
elems = object->list.objects;
RASN1Object **elems = object->list.objects;
r_x509_parse_algorithmidentifier (&crl->signature, elems[0]);
r_x509_parse_name (&crl->issuer, elems[1]);
crl->lastUpdate = r_asn1_stringify_utctime (elems[2]->sector, elems[2]->length);
@ -302,7 +299,7 @@ R_API RX509CertificateRevocationList *r_x509_parse_crl(RASN1Object *object) {
return crl;
}
void r_x509_free_algorithmidentifier (RX509AlgorithmIdentifier *ai) {
R_API void r_x509_free_algorithmidentifier(RX509AlgorithmIdentifier *ai) {
if (ai) {
// no need to free ai, since this functions is used internally
r_asn1_free_string (ai->algorithm);
@ -318,7 +315,7 @@ static void r_x509_free_validity(RX509Validity *validity) {
}
}
void r_x509_free_name (RX509Name *name) {
R_API void r_x509_free_name(RX509Name *name) {
ut32 i;
if (!name) {
return;
@ -334,7 +331,7 @@ void r_x509_free_name (RX509Name *name) {
// not freeing name since it's not allocated dinamically
}
void r_x509_free_extension (RX509Extension *ex) {
void r_x509_free_extension(RX509Extension *ex) {
if (ex) {
r_asn1_free_string (ex->extnID);
r_asn1_free_binary (ex->extnValue);