From 0803df29fc5f69628eac03ffc7b2274542b6bcd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 5 May 2025 17:31:35 +0200 Subject: [PATCH] Fix memory leak in cert_write & cert_req MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That memory leak had been present ever since the san command-line argument has been added. Tested that the following invocation is now fully valgrind clean: programs/x509/cert_write san=DN:C=NL,CN=#0000,CN=foo;DN:CN=#0000,O=foo,OU=bar,C=UK;IP:1.2.3.4;IP:4.3.2.1;URI:http\\://example.org/;URI:foo;DNS:foo.example.org;DNS:bar.example.org Signed-off-by: Manuel Pégourié-Gonnard --- programs/x509/cert_req.c | 17 +++++++++++++++++ programs/x509/cert_write.c | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index c399021916..26aed93e4f 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -497,6 +497,23 @@ exit: #endif } + cur = opt.san_list; + while (cur != NULL) { + mbedtls_x509_san_list *next = cur->next; + /* Note: mbedtls_x509_free_subject_alt_name() is not what we want here. + * It's the right thing for entries that were parsed from a certificate, + * where pointers are to the raw certificate, but here all the + * pointers were allocated while parsing from a user-provided string. */ + if (cur->node.type == MBEDTLS_X509_SAN_DIRECTORY_NAME) { + mbedtls_x509_name dn = cur->node.san.directory_name; + mbedtls_free(dn.oid.p); + mbedtls_free(dn.val.p); + mbedtls_asn1_free_named_data_list(&dn.next); + } + mbedtls_free(cur); + cur = next; + } + mbedtls_x509write_csr_free(&req); mbedtls_pk_free(&key); mbedtls_ctr_drbg_free(&ctr_drbg); diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 63872a953f..d46470274a 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -1001,6 +1001,23 @@ usage: exit_code = MBEDTLS_EXIT_SUCCESS; exit: + cur = opt.san_list; + while (cur != NULL) { + mbedtls_x509_san_list *next = cur->next; + /* Note: mbedtls_x509_free_subject_alt_name() is not what we want here. + * It's the right thing for entries that were parsed from a certificate, + * where pointers are to the raw certificate, but here all the + * pointers were allocated while parsing from a user-provided string. */ + if (cur->node.type == MBEDTLS_X509_SAN_DIRECTORY_NAME) { + mbedtls_x509_name dn = cur->node.san.directory_name; + mbedtls_free(dn.oid.p); + mbedtls_free(dn.val.p); + mbedtls_asn1_free_named_data_list(&dn.next); + } + mbedtls_free(cur); + cur = next; + } + #if defined(MBEDTLS_X509_CSR_PARSE_C) mbedtls_x509_csr_free(&csr); #endif /* MBEDTLS_X509_CSR_PARSE_C */