You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2026-10-23 21:28:56 +03:00
Limit the depth of nested containers when reading JSON.
Each level of a nested array switches to a mem context in jsonReadVar() and each level of any container recurses, so deeply nested JSON could fill the mem context stack or exhaust the C stack. JSON is read from repository info files, manifests, lock files, and object store responses, which pgBackRest does not always control. Error when the depth exceeds 32. The JSON pgBackRest reads does not nest more than a few levels.
This commit is contained in:
@@ -11,8 +11,14 @@ Convert JSON to/from KeyValue
|
||||
#include "common/debug.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/log.h"
|
||||
#include "common/macro.h"
|
||||
#include "common/type/json.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Maximum depth of nested containers when reading
|
||||
***********************************************************************************************************************************/
|
||||
#define JSON_READ_DEPTH_MAX 32
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Object types
|
||||
***********************************************************************************************************************************/
|
||||
@@ -322,7 +328,12 @@ jsonReadPush(JsonRead *const this, const JsonType type, const bool key)
|
||||
|
||||
// Add container to the stack
|
||||
if (jsonTypeContainer(type))
|
||||
{
|
||||
if (lstSize(this->stack) >= JSON_READ_DEPTH_MAX)
|
||||
THROW_FMT(JsonFormatError, "maximum depth of " STRINGIFY(JSON_READ_DEPTH_MAX) " exceeded at: %s", this->json);
|
||||
|
||||
lstAdd(this->stack, &(JsonReadStack){.type = type});
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
@@ -61,6 +61,21 @@ testRun(void)
|
||||
|
||||
TEST_ERROR(jsonReadStr(jsonReadNew(STRDEF("\"\\u1111"))), JsonFormatError, "unable to decode at: \\u1111");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("error on maximum depth");
|
||||
|
||||
String *const depthArray = strNew();
|
||||
String *const depthObject = strNew();
|
||||
|
||||
for (unsigned int depthIdx = 0; depthIdx < 32; depthIdx++)
|
||||
{
|
||||
strCatChr(depthArray, '[');
|
||||
strCatZ(depthObject, "{\"a\":");
|
||||
}
|
||||
|
||||
TEST_ERROR(jsonToVar(strNewFmt("%s{", strZ(depthArray))), JsonFormatError, "maximum depth of 32 exceeded at: {");
|
||||
TEST_ERROR(jsonValidate(strNewFmt("%s[", strZ(depthObject))), JsonFormatError, "maximum depth of 32 exceeded at: [");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("error on invalid escape");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user