1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-02-21 19:48:29 +02:00

Do not allow CATCH() to catch a fatal error.

Catching individual fatal errors was only used in testing so the tests have been updated to use other errors instead. CATCH_FATAL() is now the only way to catch fatal errors.

This simplifies the logic a bit for upcoming changes to error handling and cleanup.

Also fix an issue where passing errorMessage() directly to THROW*() would attempt to copy the message buffer instead of preserving it, which is undefined behavior. Since there were no instances of this behavior before this commit, this was not a live bug.
This commit is contained in:
David Steele 2022-08-16 16:15:48 -04:00 committed by GitHub
parent 02665a5894
commit 82786da154
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 13 deletions

View File

@ -41,6 +41,19 @@
<p>Improve warning message on backup resume.</p>
</release-item>
</release-improvement-list>
<release-development-list>
<release-item>
<github-pull-request id="1838"/>
<release-item-contributor-list>
<release-item-contributor id="david.steele"/>
<release-item-reviewer id="john.morris"/>
</release-item-contributor-list>
<p>Do not allow <code>CATCH()</code> to catch a fatal error.</p>
</release-item>
</release-development-list>
</release-core-list>
<release-doc-list>

View File

@ -302,6 +302,8 @@ errorInternalJump(void)
bool
errorInternalCatch(const ErrorType *const errorTypeCatch, const bool fatalCatch)
{
assert(fatalCatch || !errorTypeFatal(errorTypeCatch));
// If just entering error state clean up the stack
if (errorInternalState() == errorStateTry)
{
@ -371,9 +373,12 @@ errorInternalThrow(
errorContext.error.functionName = functionName;
errorContext.error.fileLine = fileLine;
// Assign message to the error
strncpy(messageBuffer, message, sizeof(messageBuffer));
messageBuffer[sizeof(messageBuffer) - 1] = 0;
// Assign message to the error. If errorMessage() is passed as the message there is no need to make a copy.
if (message != messageBuffer)
{
strncpy(messageBuffer, message, sizeof(messageBuffer));
messageBuffer[sizeof(messageBuffer) - 1] = 0;
}
errorContext.error.message = (const char *)messageBuffer;

View File

@ -145,7 +145,7 @@ Catch a specific error thrown in the try block
***********************************************************************************************************************************/
#define CATCH(errorTypeCatch) \
} \
else if (errorInternalCatch(&errorTypeCatch, true)) \
else if (errorInternalCatch(&errorTypeCatch, false)) \
{
/***********************************************************************************************************************************

View File

@ -33,7 +33,7 @@ testTryRecurse(void)
testTryRecurse();
}
CATCH(MemoryError)
CATCH(UnhandledError)
{
testTryRecurseCatch = true; // {uncoverable - catch should never be executed}
}
@ -181,20 +181,21 @@ testRun(void)
}
TRY_END();
}
CATCH(AssertError)
CATCH_FATAL()
{
assert(testErrorHandlerTryDepth == 3);
// Finally below should run even though this error has been rethrown
RETHROW();
// Change to FormatError so error can be caught by normal catches
THROW(FormatError, errorMessage());
}
// Should run even though an error has been thrown in the catch
FINALLY()
{
finallyDone = true;
}
TRY_END();
}
CATCH_FATAL()
CATCH_ANY()
{
assert(testErrorHandlerTryDepth == 2);
@ -202,7 +203,7 @@ testRun(void)
}
TRY_END();
}
CATCH(MemoryError)
CATCH(UnhandledError)
{
assert(false); // {uncoverable - catch should never be executed}
}
@ -238,7 +239,7 @@ testRun(void)
tryDone = true;
testTryRecurse();
}
CATCH(AssertError)
CATCH_FATAL()
{
assert(errorCode() == AssertError.code);
assert(strcmp(errorFileName(), TEST_PGB_PATH "/test/src/module/common/errorTest.c") == 0);

View File

@ -414,11 +414,11 @@ testRun(void)
{
memContext = MEM_CONTEXT_NEW();
TEST_RESULT_Z(memContext->name, memContextTestName, "check mem context name");
THROW(AssertError, "create failed");
THROW(FormatError, "create failed");
}
MEM_CONTEXT_NEW_END();
}
CATCH(AssertError)
CATCH(FormatError)
{
catch = true;
}