diff --git a/src/x509.c b/src/x509.c index fd87b1da4a..9dd5c53954 100644 --- a/src/x509.c +++ b/src/x509.c @@ -298,6 +298,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_create_by_OBJ( { int err = 0; WOLFSSL_X509_EXTENSION *ret = ex; + WOLFSSL_ASN1_OBJECT *newObj = NULL; WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_create_by_OBJ"); @@ -311,7 +312,18 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_create_by_OBJ( err = 1; } } - else { + + /* Duplicate the source object before freeing the existing one so that a + * caller passing the extension's own object (e.g. obtained via + * wolfSSL_X509_EXTENSION_get_object(ex)) does not read freed memory. */ + if (err == 0) { + newObj = wolfSSL_ASN1_OBJECT_dup(obj); + if (newObj == NULL) { + err = 1; + } + } + + if ((err == 0) && (ret == ex)) { /* Prevent potential memory leaks and dangling pointers. */ wolfSSL_ASN1_OBJECT_free(ret->obj); ret->obj = NULL; @@ -320,10 +332,8 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_create_by_OBJ( if (err == 0) { ret->crit = crit; - ret->obj = wolfSSL_ASN1_OBJECT_dup(obj); - if (ret->obj == NULL) { - err = 1; - } + ret->obj = newObj; + newObj = NULL; } if (err == 0) { @@ -333,6 +343,8 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_create_by_OBJ( } if (err == 1) { + /* Free the duplicate if it was created but not assigned to ret. */ + wolfSSL_ASN1_OBJECT_free(newObj); if (ret != ex) { wolfSSL_X509_EXTENSION_free(ret); } diff --git a/tests/api/test_ossl_x509_ext.c b/tests/api/test_ossl_x509_ext.c index 05d2370a87..631cd59154 100644 --- a/tests/api/test_ossl_x509_ext.c +++ b/tests/api/test_ossl_x509_ext.c @@ -905,6 +905,14 @@ int test_wolfSSL_X509_EXTENSION_create_by_OBJ(void) if (ext3 == NULL) { wolfSSL_X509_EXTENSION_free(ext2); } + /* Reuse the extension passing its own object as the source. This must not + * read freed memory (the source object aliases ext3's current object). */ + if (ext3 != NULL) { + WOLFSSL_ASN1_OBJECT* self = NULL; + ExpectNotNull(self = wolfSSL_X509_EXTENSION_get_object(ext3)); + ExpectNotNull(ext3 = wolfSSL_X509_EXTENSION_create_by_OBJ(ext3, self, + crit, str)); + } wolfSSL_X509_EXTENSION_free(ext3); ExpectIntEQ(wolfSSL_X509_get_ext_by_OBJ(NULL, NULL, -1),