On 08/30/2016 08:42 AM, Heikki Linnakangas wrote:
There's the ResourceOwner mechanism, see src/backend/utils/resowner/.
That would be the proper way to do this. Call
RegisterResourceReleaseCallback() when the context is allocated, and
have the callback free it. One pitfall to watch out for is that
RegisterResourceReleaseCallback() itself calls palloc(), and can error
out, so you have to do things in such an order that you don't leak in
that case either.

Want to take a stab at that?

Another approach is put each allocated context in a list or array in a
global variable, and to register a callback to be called at
end-of-(sub)transaction, which closes all the contexts. But the resource
owner mechanism is probably easier.

There's also PG_TRY-CATCH, that you could maybe use in the callers of
px_find_digest(), to make sure they call px_free_digest() even on error.
But that also seems difficult to use with the pgp_encrypt() pipeline.

Sure, I have attached a patch where I try to use it.

PS. I just remembered that I've wanted to refactor the pgcrypto calls
for symmetric encryption to use the newer EVP API for some time, and
even posted a patch for that
(https://www.postgresql.org/message-id/561274f1.1030...@iki.fi). I
dropped the ball back then, but I think I'll go ahead and do that now,
once we get these other OpenSSL changes in.


>From 0afeb5e075028339f28c2c2d7b407c1bcc85c4be Mon Sep 17 00:00:00 2001
From: Andreas Karlsson <andr...@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;
+	UnregisterResourceReleaseCallback(digest_ctx_free_callback, digest);
 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)
 	if (EVP_DigestInit_ex(digest->ctx, digest->algo, NULL) == 0) {
+		UnregisterResourceReleaseCallback(digest_ctx_free_callback, digest);
 		return -1;

Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:

Reply via email to