Revert "Migrate Bio to RefCounted." This reverts commit 56ab75f53c3c188367bfea8383871ddf33b4609a. It broke the return value of BIO_free, which existing callers seems to rely on (even though that return value is pretty horrific). Reverting for now so we can add tests and reland a fixed version. Change-Id: Id287aaa1ac0dbe0917ff1ac3bcd75429ebce2474 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/89627 Reviewed-by: Lily Chen <chlily@google.com> Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Xiangfei Ding <xfding@google.com> Commit-Queue: Xiangfei Ding <xfding@google.com> Auto-Submit: David Benjamin <davidben@google.com>
diff --git a/crypto/bio/bio.cc b/crypto/bio/bio.cc index e3c3ee3..7f6a052 100644 --- a/crypto/bio/bio.cc +++ b/crypto/bio/bio.cc
@@ -33,43 +33,51 @@ static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA; -Bio::Bio(const BIO_METHOD *m) : RefCounted(CheckSubClass()), method(m) { - CRYPTO_new_ex_data(&ex_data); -} - BIO *BIO_new(const BIO_METHOD *method) { - UniquePtr<Bio> ret(New<Bio>(method)); + Bio *ret = NewZeroed<Bio>(); if (ret == nullptr) { return nullptr; } - if (method->create != nullptr && !method->create(ret.get())) { + ret->method = method; + ret->shutdown = 1; + ret->references = 1; + CRYPTO_new_ex_data(&ret->ex_data); + + if (method->create != nullptr && !method->create(ret)) { + Delete(ret); return nullptr; } - return ret.release(); -} - -Bio::~Bio() { - if (method != nullptr && method->destroy != nullptr) { - method->destroy(this); - } - CRYPTO_free_ex_data(&g_ex_data_class, &ex_data); - BIO_free(BIO_pop(this)); + return ret; } int BIO_free(BIO *bio) { - if (bio == nullptr) { - return 1; - } auto *impl = FromOpaque(bio); - impl->DecRefInternal(); + + Bio *next_bio; + + for (; impl != nullptr; impl = next_bio) { + if (!CRYPTO_refcount_dec_and_test_zero(&impl->references)) { + return 0; + } + + next_bio = FromOpaque(BIO_pop(impl)); + + if (impl->method != nullptr && impl->method->destroy != nullptr) { + impl->method->destroy(impl); + } + + CRYPTO_free_ex_data(&g_ex_data_class, &impl->ex_data); + Delete(impl); + } return 1; } int BIO_up_ref(BIO *bio) { auto *impl = FromOpaque(bio); - impl->UpRefInternal(); + + CRYPTO_refcount_inc(&impl->references); return 1; }
diff --git a/crypto/bio/internal.h b/crypto/bio/internal.h index 77cd8a8..6c9e02e 100644 --- a/crypto/bio/internal.h +++ b/crypto/bio/internal.h
@@ -20,7 +20,6 @@ #include <openssl/ex_data.h> #include "../internal.h" -#include "../mem_internal.h" #if !defined(OPENSSL_NO_SOCK) #if !defined(OPENSSL_WINDOWS) @@ -53,10 +52,8 @@ BSSL_NAMESPACE_BEGIN -class Bio : public bio_st, public RefCounted<Bio> { +class Bio : public bio_st { public: - explicit Bio(const BIO_METHOD *m); - const BIO_METHOD *method; CRYPTO_EX_DATA ex_data; @@ -64,26 +61,23 @@ // integrated into |flags|, to save memory. // init is non-zero if this |BIO| has been initialised. - int init = 0; + int init; // shutdown is often used by specific |BIO_METHOD|s to determine whether // they own some underlying resource. This flag can often be controlled by // |BIO_set_close|. For example, whether an fd BIO closes the underlying fd // when it, itself, is closed. - int shutdown = 1; - int flags = 0; - int retry_reason = 0; + int shutdown; + int flags; + int retry_reason; // num is a BIO-specific value. For example, in fd BIOs it's used to store a // file descriptor. - int num = 0; - void *ptr = nullptr; + int num; + bssl::CRYPTO_refcount_t references; + void *ptr; // next_bio points to the next |BIO| in a chain. This |BIO| owns a reference // to |next_bio|. - Bio *next_bio = nullptr; // used by filter BIOs - uint64_t num_read = 0, num_write = 0; - - private: - friend RefCounted; - ~Bio(); + Bio *next_bio; // used by filter BIOs + uint64_t num_read, num_write; }; #if !defined(OPENSSL_NO_SOCK)