mirror of
https://github.com/espressif/esp-protocols.git
synced 2026-07-07 00:50:52 +02:00
fix(asio): memory leaks over ssl::stream lifetime
asio::ssl::stream leaks a significant amount (>20KB) of memory over its
lifetime.
asio::ssl::mbedtls::engine::impl has these members ...
mbedtls_ssl_context ssl_{};
mbedtls_entropy_context entropy_{};
mbedtls_ctr_drbg_context ctr_drbg_{};
mbedtls_ssl_config conf_{};
mbedtls_x509_crt public_cert_{};
mbedtls_pk_context pk_key_{};
mbedtls_x509_crt ca_cert_{};
... which are properly init'ed in its constructor ...
mbedtls_ssl_init(&ssl_);
mbedtls_ssl_config_init(&conf_);
mbedtls_ctr_drbg_init(&ctr_drbg_);
mbedtls_entropy_init(&entropy_);
mbedtls_x509_crt_init(&public_cert_);
mbedtls_pk_init(&pk_key_);
mbedtls_x509_crt_init(&ca_cert_);
... but are never free'd ... until now
~impl()
{
mbedtls_x509_crt_free(&ca_cert_);
mbedtls_pk_free(&pk_key_);
mbedtls_x509_crt_free(&public_cert_);
mbedtls_entropy_free(&entropy_);
mbedtls_ctr_drbg_free(&ctr_drbg_);
mbedtls_ssl_config_free(&conf_);
mbedtls_ssl_free(&ssl_);
}
asio::ssl::mbedtls::engine::impl::configure calls ...
mbedtls_x509_crt_init(&public_cert_);
mbedtls_pk_init(&pk_key_);
mbedtls_x509_crt_init(&ca_cert_);
... again without first free'ing any resources that might be held by such.
now this is done first:
mbedtls_x509_crt_free(&ca_cert_);
mbedtls_pk_free(&pk_key_);
mbedtls_x509_crt_free(&public_cert_);
asio::ssl::engine has this member
std::pair<std::shared_ptr<bio>, std::shared_ptr<bio>> bio_;
which is made in its constructor
explicit engine(std::shared_ptr<context> ctx): ctx_(std::move(ctx)),
bio_(bio::new_pair("mbedtls-engine")), state_(IDLE), verify_mode_(0) {}
asio::ssl::mbedtls::bio::new_pair creates a cyclic reference between its
paired elements
static std::pair<std::shared_ptr<bio>, std::shared_ptr<bio>> new_pair(const char *error_location)
{
auto b1 = std::shared_ptr<bio>(new (std::nothrow) bio);
auto b2 = std::shared_ptr<bio>(new (std::nothrow) bio);
if (b1 == nullptr || b2 == nullptr) {
throw_alloc_failure(error_location);
} else {
b1->peer_ = b2;
b2->peer_ = b1;
}
return std::make_pair(b1, b2);
}
there is no asio::ssl::engine destructor to untie this cycle so when the
pair member is destroyed, its elements will leak.
a destructor is needed to fix this ...
~engine()
{
bio::untie_pair(bio_);
}
... along with untie_pair ...
// untie cyclic shared_ptr references made by new_pair in preparation for destruction
static void untie_pair(std::pair<std::shared_ptr<bio>, std::shared_ptr<bio>>& pair)
{
if (pair.first) {
pair.first->peer_.reset();
}
if (pair.second) {
pair.second->peer_.reset();
}
}
This commit is contained in:
@@ -100,6 +100,17 @@ public:
|
||||
return std::make_pair(b1, b2);
|
||||
}
|
||||
|
||||
// untie cyclic shared_ptr references made by new_pair in preparation for destruction
|
||||
static void untie_pair(std::pair<std::shared_ptr<bio>, std::shared_ptr<bio>>& pair)
|
||||
{
|
||||
if (pair.first) {
|
||||
pair.first->peer_.reset();
|
||||
}
|
||||
if (pair.second) {
|
||||
pair.second->peer_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<uint8_t, BIO_SIZE> data_ {};
|
||||
size_t size_ {BIO_SIZE};
|
||||
|
||||
@@ -62,6 +62,11 @@ public:
|
||||
explicit engine(std::shared_ptr<context> ctx): ctx_(std::move(ctx)),
|
||||
bio_(bio::new_pair("mbedtls-engine")), state_(IDLE), verify_mode_(0) {}
|
||||
|
||||
~engine()
|
||||
{
|
||||
bio::untie_pair(bio_);
|
||||
}
|
||||
|
||||
void set_verify_mode(asio::ssl::verify_mode mode)
|
||||
{
|
||||
verify_mode_ = mode;
|
||||
@@ -232,8 +237,22 @@ private:
|
||||
mbedtls_x509_crt_init(&ca_cert_);
|
||||
}
|
||||
|
||||
~impl()
|
||||
{
|
||||
mbedtls_x509_crt_free(&ca_cert_);
|
||||
mbedtls_pk_free(&pk_key_);
|
||||
mbedtls_x509_crt_free(&public_cert_);
|
||||
mbedtls_entropy_free(&entropy_);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg_);
|
||||
mbedtls_ssl_config_free(&conf_);
|
||||
mbedtls_ssl_free(&ssl_);
|
||||
}
|
||||
|
||||
bool configure(context *ctx, bool is_client_not_server, int mbedtls_verify_mode)
|
||||
{
|
||||
mbedtls_x509_crt_free(&ca_cert_);
|
||||
mbedtls_pk_free(&pk_key_);
|
||||
mbedtls_x509_crt_free(&public_cert_);
|
||||
mbedtls_x509_crt_init(&public_cert_);
|
||||
mbedtls_pk_init(&pk_key_);
|
||||
mbedtls_x509_crt_init(&ca_cert_);
|
||||
|
||||
Reference in New Issue
Block a user