Author: ivan
Date: Wed Jul 8 19:24:44 2026
New Revision: 1936009
Log:
bcrypt: Destroy BCrypt hash context using BCryptDestroyHash(). We allocate
memory for BCrypt hash context from APR pool, so existing code didn't have
memory leak. But in theory BCrypt may have other resources besides memory
used by context itself.
* subversion/libsvn_subr/checksum_bcrypt.c
(bcrypt_ctx_cleanup): New. APR pool cleanup handler to cleanup bcrypt_ctx_t.
(bcrypt_ctx_init): Register APR pool cleanup handler.
(bcrypt_ctx_reset, bcrypt_checksum): Destroy BCrypt hash context using
BCryptDestroyHash().
Modified:
subversion/trunk/subversion/libsvn_subr/checksum_bcrypt.c
Modified: subversion/trunk/subversion/libsvn_subr/checksum_bcrypt.c
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/checksum_bcrypt.c Wed Jul 8
18:45:04 2026 (r1936008)
+++ subversion/trunk/subversion/libsvn_subr/checksum_bcrypt.c Wed Jul 8
19:24:44 2026 (r1936009)
@@ -93,6 +93,25 @@ typedef struct bcrypt_ctx_t
apr_pool_t *pool;
} bcrypt_ctx_t;
+/* A cleanup handler. */
+static apr_status_t
+bcrypt_ctx_cleanup(void *data)
+{
+ bcrypt_ctx_t *ctx = data;
+
+ if (ctx->handle)
+ {
+ NTSTATUS status = BCryptDestroyHash(ctx->handle);
+
+ if (!BCRYPT_SUCCESS(status))
+ SVN_ERR_MALFUNCTION_NO_RETURN();
+
+ ctx->handle = NULL;
+ }
+
+ return APR_SUCCESS;
+}
+
static svn_error_t *
bcrypt_ctx_init(algorithm_state_t *algorithm,
bcrypt_ctx_t *ctx)
@@ -102,8 +121,12 @@ bcrypt_ctx_init(algorithm_state_t *algor
SVN_ERR(svn_atomic__init_once(&algorithm->initialized, algorithm_init,
algorithm, NULL));
- if (! ctx->object_buf)
- ctx->object_buf = apr_pcalloc(ctx->pool, algorithm->object_length);
+ if (!ctx->object_buf)
+ {
+ ctx->object_buf = apr_pcalloc(ctx->pool, algorithm->object_length);
+ apr_pool_cleanup_register(ctx->pool, ctx, bcrypt_ctx_cleanup,
+ apr_pool_cleanup_null);
+ }
SVN_ERR(handle_error(BCryptCreateHash(algorithm->alg_handle,
&handle,
@@ -162,8 +185,14 @@ bcrypt_ctx_final(algorithm_state_t *algo
static svn_error_t *
bcrypt_ctx_reset(algorithm_state_t *algorithm, bcrypt_ctx_t *ctx)
{
+ if (ctx->handle)
+ {
+ SVN_ERR(handle_error(BCryptDestroyHash(ctx->handle)));
+ ctx->handle = NULL;
+ }
+
memset(ctx->object_buf, 0, algorithm->object_length);
- ctx->handle = NULL;
+
return SVN_NO_ERROR;
}
@@ -175,6 +204,7 @@ bcrypt_checksum(algorithm_state_t *algor
{
BCRYPT_HANDLE handle;
void *object_buf;
+ svn_error_t *err;
SVN_ERR(svn_atomic__init_once(&algorithm->initialized, algorithm_init,
algorithm, NULL));
@@ -198,16 +228,29 @@ bcrypt_checksum(algorithm_state_t *algor
else
block = UINT_MAX;
- SVN_ERR(handle_error(BCryptHashData(handle, (PUCHAR)data, block,
- /* dwFlags */ 0)));
+ err = handle_error(BCryptHashData(handle, (PUCHAR)data, block,
+ /* dwFlags */ 0));
+ if (err)
+ {
+ return svn_error_compose_create(
+ err, handle_error(BCryptDestroyHash(handle)));
+ }
len -= block;
data += block;
}
- SVN_ERR(handle_error(BCryptFinishHash(handle, digest,
- algorithm->hash_length,
- /* dwFlags */ 0)));
+ err = handle_error(BCryptFinishHash(handle, digest,
+ algorithm->hash_length,
+ /* dwFlags */ 0));
+
+ if (err)
+ {
+ return svn_error_compose_create(err,
+ handle_error(BCryptDestroyHash(handle)));
+ }
+
+ SVN_ERR(handle_error(BCryptDestroyHash(handle)));
return SVN_NO_ERROR;
}