mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
AK: Guard JSON parser against deep nesting
Add a maximum nesting depth check in JsonParser so deeply nested arrays/objects from untrusted input cannot blow the call stack. Add regression tests for excessive nesting rejection and reasonable nesting acceptance.
This commit is contained in:
Notes:
github-actions[bot]
2026-03-27 14:30:48 +00:00
Author: https://github.com/RubenKelevra 🔰 Commit: https://github.com/LadybirdBrowser/ladybird/commit/14a0f004006 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8242 Reviewed-by: https://github.com/AtkinsSJ ✅
@@ -8,6 +8,7 @@
|
||||
#include <AK/JsonArray.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/JsonParser.h>
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <AK/StringConversions.h>
|
||||
#include <math.h>
|
||||
|
||||
@@ -18,6 +19,8 @@ constexpr bool is_space(int ch)
|
||||
return ch == '\t' || ch == '\n' || ch == '\r' || ch == ' ';
|
||||
}
|
||||
|
||||
constexpr StringView exceeded_max_nesting_depth_error = "JsonParser: Exceeded maximum nesting depth"sv;
|
||||
|
||||
ErrorOr<JsonValue> JsonParser::parse(StringView input)
|
||||
{
|
||||
JsonParser parser(input);
|
||||
@@ -137,6 +140,11 @@ ErrorOr<ByteString> JsonParser::consume_and_unescape_string()
|
||||
|
||||
ErrorOr<JsonValue> JsonParser::parse_object()
|
||||
{
|
||||
if (m_current_nesting_depth >= max_nesting_depth)
|
||||
return Error::from_string_view(exceeded_max_nesting_depth_error);
|
||||
++m_current_nesting_depth;
|
||||
ScopeGuard nesting_depth_guard { [this] { --m_current_nesting_depth; } };
|
||||
|
||||
JsonObject object;
|
||||
if (!consume_specific('{'))
|
||||
return Error::from_string_literal("JsonParser: Expected '{'");
|
||||
@@ -168,6 +176,11 @@ ErrorOr<JsonValue> JsonParser::parse_object()
|
||||
|
||||
ErrorOr<JsonValue> JsonParser::parse_array()
|
||||
{
|
||||
if (m_current_nesting_depth >= max_nesting_depth)
|
||||
return Error::from_string_view(exceeded_max_nesting_depth_error);
|
||||
++m_current_nesting_depth;
|
||||
ScopeGuard nesting_depth_guard { [this] { --m_current_nesting_depth; } };
|
||||
|
||||
JsonArray array;
|
||||
if (!consume_specific('['))
|
||||
return Error::from_string_literal("JsonParser: Expected '['");
|
||||
|
||||
@@ -32,6 +32,10 @@ private:
|
||||
ErrorOr<JsonValue> parse_false();
|
||||
ErrorOr<JsonValue> parse_true();
|
||||
ErrorOr<JsonValue> parse_null();
|
||||
|
||||
// Keep recursive parsing depth bounded so untrusted JSON cannot overflow the call stack.
|
||||
static constexpr size_t max_nesting_depth { 512 };
|
||||
size_t m_current_nesting_depth { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user