From f7489592d6518a98a70a890dedbabb359e5da79a Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 15 May 2021 10:51:47 +0400 Subject: [PATCH] Fix BIO_new_mem_buf leaks --- Telegram/SourceFiles/_other/packer.cpp | 39 +++++++++++++++++-- Telegram/SourceFiles/core/update_checker.cpp | 39 +++++++++++++++++-- .../details/mtproto_rsa_public_key.cpp | 18 ++++++--- 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/Telegram/SourceFiles/_other/packer.cpp b/Telegram/SourceFiles/_other/packer.cpp index 99fae21f12..630c0b9408 100644 --- a/Telegram/SourceFiles/_other/packer.cpp +++ b/Telegram/SourceFiles/_other/packer.cpp @@ -47,6 +47,18 @@ typedef signed int int32; namespace{ +struct BIODeleter { + void operator()(BIO *value) { + BIO_free(value); + } +}; + +inline auto makeBIO(const void *buf, int len) { + return std::unique_ptr{ + BIO_new_mem_buf(buf, len), + }; +} + inline uint32 sha1Shift(uint32 v, uint32 shift) { return ((v << shift) | (v >> (32 - shift))); } @@ -430,7 +442,15 @@ int main(int argc, char *argv[]) uint32 siglen = 0; cout << "Signing..\n"; - RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast((BetaChannel || AlphaVersion) ? PrivateBetaKey : PrivateKey), -1), 0, 0, 0); + RSA *prKey = [] { + const auto bio = makeBIO( + const_cast( + (BetaChannel || AlphaVersion) + ? PrivateBetaKey + : PrivateKey), + -1); + return PEM_read_bio_RSAPrivateKey(bio.get(), 0, 0, 0); + }(); if (!prKey) { cout << "Could not read RSA private key!\n"; return -1; @@ -453,7 +473,15 @@ int main(int argc, char *argv[]) } cout << "Checking signature..\n"; - RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast((BetaChannel || AlphaVersion) ? PublicBetaKey : PublicKey), -1), 0, 0, 0); + RSA *pbKey = [] { + const auto bio = makeBIO( + const_cast( + (BetaChannel || AlphaVersion) + ? PublicBetaKey + : PublicKey), + -1); + return PEM_read_bio_RSAPublicKey(bio.get(), 0, 0, 0); + }(); if (!pbKey) { cout << "Could not read RSA public key!\n"; return -1; @@ -510,7 +538,12 @@ QString countAlphaVersionSignature(quint64 version) { // duplicated in autoupdat uint32 siglen = 0; - RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast(cAlphaPrivateKey.constData()), -1), 0, 0, 0); + RSA *prKey = [] { + const auto bio = makeBIO( + const_cast(cAlphaPrivateKey.constData()), + -1); + return PEM_read_bio_RSAPrivateKey(bio.get(), 0, 0, 0); + }(); if (!prKey) { cout << "Error: Could not read alpha private key!\n"; return QString(); diff --git a/Telegram/SourceFiles/core/update_checker.cpp b/Telegram/SourceFiles/core/update_checker.cpp index 5f42cfb756..f621f164a9 100644 --- a/Telegram/SourceFiles/core/update_checker.cpp +++ b/Telegram/SourceFiles/core/update_checker.cpp @@ -76,6 +76,18 @@ using VersionChar = wchar_t; using Loader = MTP::AbstractDedicatedLoader; +struct BIODeleter { + void operator()(BIO *value) { + BIO_free(value); + } +}; + +inline auto MakeBIO(const void *buf, int len) { + return std::unique_ptr{ + BIO_new_mem_buf(buf, len), + }; +} + class Checker : public base::has_weak_ptr { public: Checker(bool testing); @@ -289,7 +301,15 @@ bool UnpackUpdate(const QString &filepath) { return false; } - RSA *pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast(AppBetaVersion ? UpdatesPublicBetaKey : UpdatesPublicKey), -1), 0, 0, 0); + RSA *pbKey = [] { + const auto bio = MakeBIO( + const_cast( + AppBetaVersion + ? UpdatesPublicBetaKey + : UpdatesPublicKey), + -1); + return PEM_read_bio_RSAPublicKey(bio.get(), 0, 0, 0); + }(); if (!pbKey) { LOG(("Update Error: cant read public rsa key!")); return false; @@ -298,7 +318,15 @@ bool UnpackUpdate(const QString &filepath) { RSA_free(pbKey); // try other public key, if we update from beta to stable or vice versa - pbKey = PEM_read_bio_RSAPublicKey(BIO_new_mem_buf(const_cast(AppBetaVersion ? UpdatesPublicKey : UpdatesPublicBetaKey), -1), 0, 0, 0); + pbKey = [] { + const auto bio = MakeBIO( + const_cast( + AppBetaVersion + ? UpdatesPublicKey + : UpdatesPublicBetaKey), + -1); + return PEM_read_bio_RSAPublicKey(bio.get(), 0, 0, 0); + }(); if (!pbKey) { LOG(("Update Error: cant read public rsa key!")); return false; @@ -1649,7 +1677,12 @@ QString countAlphaVersionSignature(uint64 version) { // duplicated in packer.cpp uint32 siglen = 0; - RSA *prKey = PEM_read_bio_RSAPrivateKey(BIO_new_mem_buf(const_cast(cAlphaPrivateKey().constData()), -1), 0, 0, 0); + RSA *prKey = [] { + const auto bio = MakeBIO( + const_cast(cAlphaPrivateKey().constData()), + -1); + return PEM_read_bio_RSAPrivateKey(bio.get(), 0, 0, 0); + }(); if (!prKey) { LOG(("Error: Could not read alpha private key!")); return QString(); diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_rsa_public_key.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_rsa_public_key.cpp index 8d47ed8225..a053a18ac0 100644 --- a/Telegram/SourceFiles/mtproto/details/mtproto_rsa_public_key.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_rsa_public_key.cpp @@ -54,6 +54,12 @@ enum class Format { Unknown, }; +struct BIODeleter { + void operator()(BIO *value) { + BIO_free(value); + } +}; + Format GuessFormat(bytes::const_span key) { const auto array = QByteArray::fromRawData( reinterpret_cast(key.data()), @@ -68,14 +74,16 @@ Format GuessFormat(bytes::const_span key) { RSA *CreateRaw(bytes::const_span key) { const auto format = GuessFormat(key); - const auto bio = BIO_new_mem_buf( - const_cast(key.data()), - key.size()); + const auto bio = std::unique_ptr{ + BIO_new_mem_buf( + const_cast(key.data()), + key.size()), + }; switch (format) { case Format::RSAPublicKey: - return PEM_read_bio_RSAPublicKey(bio, nullptr, nullptr, nullptr); + return PEM_read_bio_RSAPublicKey(bio.get(), nullptr, nullptr, nullptr); case Format::RSA_PUBKEY: - return PEM_read_bio_RSA_PUBKEY(bio, nullptr, nullptr, nullptr); + return PEM_read_bio_RSA_PUBKEY(bio.get(), nullptr, nullptr, nullptr); } Unexpected("format in RSAPublicKey::Private::Create."); }