From 0afeb5e075028339f28c2c2d7b407c1bcc85c4be Mon Sep 17 00:00:00 2001
From: Andreas Karlsson <andreas@proxel.se>
Date: Sun, 4 Sep 2016 18:44:49 +0200
Subject: [PATCH] Add callback for always freeing digest context

---
 contrib/pgcrypto/openssl.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 6586d32..68a6956 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -32,6 +32,7 @@
 #include "postgres.h"
 
 #include "px.h"
+#include "utils/resowner.h"
 
 #include <openssl/evp.h>
 #include <openssl/blowfish.h>
@@ -98,16 +99,30 @@ digest_finish(PX_MD *h, uint8 *dst)
 }
 
 static void
+digest_ctx_free_callback(ResourceReleasePhase phase,
+						 bool isCommit,
+						 bool isTopLevel,
+						 void *arg)
+{
+	OSSLDigest *digest = arg;
+
+	EVP_MD_CTX_destroy(digest->ctx);
+	UnregisterResourceReleaseCallback(digest_ctx_free_callback, digest);
+}
+
+static void
 digest_free(PX_MD *h)
 {
 	OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
 
 	EVP_MD_CTX_destroy(digest->ctx);
+	UnregisterResourceReleaseCallback(digest_ctx_free_callback, digest);
 
 	px_free(digest);
 	px_free(h);
 }
 
+
 static int	px_openssl_initialized = 0;
 
 /* PUBLIC functions */
@@ -131,6 +146,9 @@ px_find_digest(const char *name, PX_MD **res)
 
 	digest = px_alloc(sizeof(*digest));
 	digest->algo = md;
+	digest->ctx = NULL;
+
+	RegisterResourceReleaseCallback(digest_ctx_free_callback, digest);
 
 	digest->ctx = EVP_MD_CTX_create();
 	if (digest->ctx == NULL)
@@ -139,6 +157,7 @@ px_find_digest(const char *name, PX_MD **res)
 	EVP_MD_CTX_init(digest->ctx);
 	if (EVP_DigestInit_ex(digest->ctx, digest->algo, NULL) == 0) {
 		EVP_MD_CTX_destroy(digest->ctx);
+		UnregisterResourceReleaseCallback(digest_ctx_free_callback, digest);
 		return -1;
 	}
 
-- 
2.9.3

