diff --git a/crypto/bytestring/cbb.c b/crypto/bytestring/cbb.c index 1da6a21e..5d7485a8 100644 --- a/crypto/bytestring/cbb.c +++ b/crypto/bytestring/cbb.c @@ -70,6 +70,10 @@ int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) { void CBB_cleanup(CBB *cbb) { if (cbb->base) { + /* Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They + * are implicitly discarded when the parent is flushed or cleaned up. */ + assert(cbb->is_top_level); + if (cbb->base->can_resize) { OPENSSL_free(cbb->base->buf); } diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h index 1b1a0a9c..6faab3c5 100644 --- a/include/openssl/bytestring.h +++ b/include/openssl/bytestring.h @@ -270,7 +270,11 @@ OPENSSL_EXPORT int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len); /* CBB_cleanup frees all resources owned by |cbb| and other |CBB| objects * writing to the same buffer. This should be used in an error case where a - * serialisation is abandoned. */ + * serialisation is abandoned. + * + * This function can only be called on a "top level" |CBB|, i.e. one initialised + * with |CBB_init| or |CBB_init_fixed|, or a |CBB| set to the zero state with + * |CBB_zero|. */ OPENSSL_EXPORT void CBB_cleanup(CBB *cbb); /* CBB_finish completes any pending length prefix and sets |*out_data| to a