diff --git a/doc/xml/release.xml b/doc/xml/release.xml
index da073a84e..fdb167367 100644
--- a/doc/xml/release.xml
+++ b/doc/xml/release.xml
@@ -90,6 +90,10 @@
Change infoArchiveCheckPg()
to display the version as a string (e.g. 9.4) instead of the integer representation (e.g. 90400) when throwing an error.
+
+ Add memContextCallbackClear()
to prevent double free()
calls.
+
+
Merge crypto/random module into crypto/crypto.
diff --git a/src/common/memContext.c b/src/common/memContext.c
index 7f9dbe94f..f4b7879f5 100644
--- a/src/common/memContext.c
+++ b/src/common/memContext.c
@@ -265,6 +265,32 @@ memContextCallback(MemContext *this, void (*callbackFunction)(void *), void *cal
FUNCTION_TEST_RESULT_VOID();
}
+/***********************************************************************************************************************************
+Clear the mem context callback. This is usually done in the object free method after resources have been freed but before
+memContextFree() is called. The goal is to prevent the object free method from being called more than once.
+***********************************************************************************************************************************/
+void
+memContextCallbackClear(MemContext *this)
+{
+ FUNCTION_TEST_BEGIN();
+ FUNCTION_TEST_PARAM(MEM_CONTEXT, this);
+
+ FUNCTION_TEST_ASSERT(this != NULL);
+ FUNCTION_TEST_END();
+
+ // Error if context is not active or freeing
+ ASSERT(this->state == memContextStateActive || this->state == memContextStateFreeing);
+
+ // Top context cannot have a callback
+ ASSERT(this != memContextTop());
+
+ // Clear callback function and argument
+ this->callbackFunction = NULL;
+ this->callbackArgument = NULL;
+
+ FUNCTION_TEST_RESULT_VOID();
+}
+
/***********************************************************************************************************************************
Allocate memory in the memory context and optionally zero it.
***********************************************************************************************************************************/
diff --git a/src/common/memContext.h b/src/common/memContext.h
index b4113fc08..c15a3688d 100644
--- a/src/common/memContext.h
+++ b/src/common/memContext.h
@@ -66,6 +66,7 @@ Use the MEM_CONTEXT*() macros when possible rather than implement error-handling
MemContext *memContextNew(const char *name);
void memContextMove(MemContext *this, MemContext *parentNew);
void memContextCallback(MemContext *this, void (*callbackFunction)(void *), void *callbackArgument);
+void memContextCallbackClear(MemContext *this);
MemContext *memContextSwitch(MemContext *this);
void memContextFree(MemContext *this);
diff --git a/src/common/regExp.c b/src/common/regExp.c
index c8add9caf..849618e96 100644
--- a/src/common/regExp.c
+++ b/src/common/regExp.c
@@ -107,6 +107,8 @@ regExpFree(RegExp *this)
if (this != NULL)
{
regfree(&this->regExp);
+
+ memContextCallbackClear(this->memContext);
memContextFree(this->memContext);
}
diff --git a/src/compress/gzipCompress.c b/src/compress/gzipCompress.c
index 77197753a..e68ec2ae4 100644
--- a/src/compress/gzipCompress.c
+++ b/src/compress/gzipCompress.c
@@ -184,7 +184,7 @@ gzipCompressToLog(const GzipCompress *this)
{
return strNewFmt(
"{inputSame: %s, done: %s, flushing: %s, availIn: %u}", cvtBoolToConstZ(this->inputSame), cvtBoolToConstZ(this->done),
- cvtBoolToConstZ(this->done), this->stream != NULL ? this->stream->avail_in : 0);
+ cvtBoolToConstZ(this->done), this->stream->avail_in);
}
/***********************************************************************************************************************************
@@ -199,12 +199,10 @@ gzipCompressFree(GzipCompress *this)
if (this != NULL)
{
- if (this->stream != NULL)
- {
- deflateEnd(this->stream);
- this->stream = NULL;
- }
+ deflateEnd(this->stream);
+ this->stream = NULL;
+ memContextCallbackClear(this->memContext);
memContextFree(this->memContext);
}
diff --git a/src/compress/gzipDecompress.c b/src/compress/gzipDecompress.c
index 1a067da4e..a917bfd53 100644
--- a/src/compress/gzipDecompress.c
+++ b/src/compress/gzipDecompress.c
@@ -159,7 +159,7 @@ gzipDecompressToLog(const GzipDecompress *this)
{
return strNewFmt(
"{inputSame: %s, done: %s, availIn: %u}", cvtBoolToConstZ(this->inputSame), cvtBoolToConstZ(this->done),
- this->stream != NULL ? this->stream->avail_in : 0);
+ this->stream->avail_in);
}
/***********************************************************************************************************************************
@@ -174,12 +174,9 @@ gzipDecompressFree(GzipDecompress *this)
if (this != NULL)
{
- if (this->stream != NULL)
- {
- inflateEnd(this->stream);
- this->stream = NULL;
- }
+ inflateEnd(this->stream);
+ memContextCallbackClear(this->memContext);
memContextFree(this->memContext);
}
diff --git a/src/crypto/cipherBlock.c b/src/crypto/cipherBlock.c
index ac10937ec..5144b155c 100644
--- a/src/crypto/cipherBlock.c
+++ b/src/crypto/cipherBlock.c
@@ -291,6 +291,7 @@ cipherBlockFree(CipherBlock *this)
EVP_CIPHER_CTX_cleanup(this->cipherContext);
// Free mem context
+ memContextCallbackClear(this->memContext);
memContextFree(this->memContext);
FUNCTION_DEBUG_RESULT_VOID();
diff --git a/src/crypto/hash.c b/src/crypto/hash.c
index 0d2b6cad1..9c1e0c574 100644
--- a/src/crypto/hash.c
+++ b/src/crypto/hash.c
@@ -219,12 +219,9 @@ cryptoHashFree(CryptoHash *this)
if (this != NULL)
{
- if (this->hashContext != NULL)
- {
- EVP_MD_CTX_destroy(this->hashContext);
- this->hashContext = NULL;
- }
+ EVP_MD_CTX_destroy(this->hashContext);
+ memContextCallbackClear(this->memContext);
memContextFree(this->memContext);
}
@@ -295,7 +292,6 @@ cryptoHashOneStr(const String *type, String *message)
FUNCTION_TEST_RESULT(BUFFER, cryptoHashOneC(type, (const unsigned char *)strPtr(message), strSize(message)));
}
-
/***********************************************************************************************************************************
Get hmac for one message/key
***********************************************************************************************************************************/
diff --git a/src/storage/driver/posix/fileRead.c b/src/storage/driver/posix/fileRead.c
index 6cc2ae01c..0b33d3bb5 100644
--- a/src/storage/driver/posix/fileRead.c
+++ b/src/storage/driver/posix/fileRead.c
@@ -250,6 +250,8 @@ storageDriverPosixFileReadFree(StorageDriverPosixFileRead *this)
if (this != NULL)
{
storageDriverPosixFileReadClose(this);
+
+ memContextCallbackClear(this->memContext);
memContextFree(this->memContext);
}
diff --git a/src/storage/driver/posix/fileWrite.c b/src/storage/driver/posix/fileWrite.c
index 895486fb5..92ae554de 100644
--- a/src/storage/driver/posix/fileWrite.c
+++ b/src/storage/driver/posix/fileWrite.c
@@ -354,6 +354,8 @@ storageDriverPosixFileWriteFree(StorageDriverPosixFileWrite *this)
if (this != NULL)
{
storageDriverPosixFileWriteClose(this);
+
+ memContextCallbackClear(this->memContext);
memContextFree(this->memContext);
}
diff --git a/test/src/module/common/memContextTest.c b/test/src/module/common/memContextTest.c
index baa2a3666..e7bbf6bd5 100644
--- a/test/src/module/common/memContextTest.c
+++ b/test/src/module/common/memContextTest.c
@@ -232,6 +232,10 @@ testRun(void)
memContextCallback(memContext, (MemContextCallback)testFree, memContext),
AssertError, "callback is already set for context 'test-callback'");
+ // Clear and reset it
+ memContextCallbackClear(memContext);
+ memContextCallback(memContext, (MemContextCallback)testFree, memContext);
+
memContextFree(memContext);
TEST_RESULT_PTR(memContextCallbackArgument, memContext, "callback argument is context");
}
diff --git a/test/src/module/compress/gzipTest.c b/test/src/module/compress/gzipTest.c
index b769480d2..1b99f0dd9 100644
--- a/test/src/module/compress/gzipTest.c
+++ b/test/src/module/compress/gzipTest.c
@@ -170,8 +170,6 @@ testRun(void)
decompress->inputSame = true;
decompress->done = true;
- inflateEnd(decompress->stream);
- decompress->stream = NULL;
TEST_RESULT_STR(strPtr(gzipDecompressToLog(decompress)), "{inputSame: true, done: true, availIn: 0}", "format object");
}