mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-28 23:50:40 +00:00
Fix ASAN crash spotted after r_str_ndup refactoring in x509 (#18481)
* Reproducer: r2 SEGV-a94-0b5-0a6
This commit is contained in:
parent
dac5c3850e
commit
2b8671012f
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user