pgbackrest.git / summary / log / commit / refs

commit    fe0fd71be2e9754491cbbdcde79e7a7cc87f2e7b
Author:   David Steele <david@pgmasters.net>
Date:     Thu Mar 30 05:00:58 2023 +0000

    Convert the result of zNewFmt() into an object.
    
    The result is not intended to be freed directly so this makes memory tracking more accurate. Fix a few places where memory was leaking after a call to zNewFmt().
    
    Also update an assert to make it clearer.


src/common/type/buffer.c | 9 ++++++--- src/common/type/stringZ.c | 14 ++++++++++++-- src/storage/helper.c | 2 +- test/src/module/common/typeStringTest.c | 17 +++++++++++++++++ test/src/module/storage/posixTest.c | 7 ++++++- 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/common/type/buffer.c b/src/common/type/buffer.c index 74d9d6a06..43418936a 100644 --- a/src/common/type/buffer.c +++ b/src/common/type/buffer.c @@ -343,7 +343,10 @@ bufUsedZero(Buffer *this) FN_EXTERN void bufToLog(const Buffer *const this, StringStatic *const debugLog) { - strStcFmt( - debugLog, "{used: %zu, size: %zu%s", bufUsed(this), bufSize(this), - bufSizeLimit(this) ? zNewFmt(", sizeAlloc: %zu}", bufSizeAlloc(this)) : "}"); + strStcFmt(debugLog, "{used: %zu, size: %zu", bufUsed(this), bufSize(this)); + + if (bufSizeLimit(this)) + strStcFmt(debugLog, ", sizeAlloc: %zu", bufSizeAlloc(this)); + + strStcCatChr(debugLog, '}'); } diff --git a/src/common/type/stringZ.c b/src/common/type/stringZ.c index 250ef2e37..fc6a7f3ac 100644 --- a/src/common/type/stringZ.c +++ b/src/common/type/stringZ.c @@ -8,6 +8,7 @@ Zero-Terminated String Handler #include "common/debug.h" #include "common/memContext.h" +#include "common/type/object.h" #include "common/type/stringZ.h" /**********************************************************************************************************************************/ @@ -20,13 +21,22 @@ zNewFmt(const char *const format, ...) ASSERT(format != NULL); - // Determine how long the allocated string needs to be and create object + // Determine how long the allocated string needs to be va_list argumentList; va_start(argumentList, format); const size_t size = (size_t)vsnprintf(NULL, 0, format, argumentList) + 1; - char *const result = memNew(size); va_end(argumentList); + // Allocate the string as extra or a separate allocation based on how large it is + char *result; + + OBJ_NEW_BASE_EXTRA_BEGIN( + char *, size > MEM_CONTEXT_ALLOC_EXTRA_MAX ? 0 : (uint16_t)size, .allocQty = size > MEM_CONTEXT_ALLOC_EXTRA_MAX ? 1 : 0) + { + result = size > MEM_CONTEXT_ALLOC_EXTRA_MAX ? memNew(size) : OBJ_NEW_ALLOC(); + } + OBJ_NEW_END(); + // Format string va_start(argumentList, format); vsnprintf(result, size, format, argumentList); diff --git a/src/storage/helper.c b/src/storage/helper.c index 9ea52d37b..6b47518b5 100644 --- a/src/storage/helper.c +++ b/src/storage/helper.c @@ -340,7 +340,7 @@ storageRepoPathExpression(const String *const expression, const String *const pa else THROW_FMT(AssertError, "invalid expression '%s'", strZ(expression)); - ASSERT(result != 0); + ASSERT(result != NULL); FUNCTION_TEST_RETURN(STRING, result); } diff --git a/test/src/module/common/typeStringTest.c b/test/src/module/common/typeStringTest.c index b600da3fd..1a85dee16 100644 --- a/test/src/module/common/typeStringTest.c +++ b/test/src/module/common/typeStringTest.c @@ -705,7 +705,24 @@ testRun(void) // ***************************************************************************************************************************** if (testBegin("z*()")) { + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("small string"); + TEST_RESULT_Z(zNewFmt("id=%d", 777), "id=777", "format"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("string large enough to need separate allocation"); + + char *format = memNew(MEM_CONTEXT_ALLOC_EXTRA_MAX + 1); + memset(format, 'A', MEM_CONTEXT_ALLOC_EXTRA_MAX); + format[MEM_CONTEXT_ALLOC_EXTRA_MAX] = '\0'; + format[0] = '%'; + format[1] = 's'; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + TEST_RESULT_Z(zNewFmt(format, "%s"), format, "compare"); +#pragma GCC diagnostic pop } // ***************************************************************************************************************************** diff --git a/test/src/module/storage/posixTest.c b/test/src/module/storage/posixTest.c index b57566eea..6c885bd2b 100644 --- a/test/src/module/storage/posixTest.c +++ b/test/src/module/storage/posixTest.c @@ -19,7 +19,12 @@ storageTestPathExpression(const String *expression, const String *path) String *result = NULL; if (strcmp(strZ(expression), "<TEST>") == 0) - result = strNewFmt("test%s", path == NULL ? "" : zNewFmt("/%s", strZ(path))); + { + result = strCatZ(strNew(), "test"); + + if (path != NULL) + strCatFmt(result, "/%s", strZ(path)); + } else if (strcmp(strZ(expression), "<NULL>") != 0) THROW_FMT(AssertError, "invalid expression '%s'", strZ(expression)); [parent: 295b53e8453b]