diff options
author | ionagamed <ionagamed@yandex-team.com> | 2023-11-29 08:16:34 +0300 |
---|---|---|
committer | ionagamed <ionagamed@yandex-team.com> | 2023-11-29 08:51:03 +0300 |
commit | 55fc158d4d2d8ae4d9f026e1afac03c7daae294d (patch) | |
tree | bff2aa2edeae94bbf21a7a9875c6d8a1cbe8974c /library/cpp/json/ut/json_reader_ut.cpp | |
parent | 4c48882379d93a43bd74060add09e309ce5e5002 (diff) | |
download | ydb-55fc158d4d2d8ae4d9f026e1afac03c7daae294d.tar.gz |
library/json: add MaxDepth and iterative parsing into config
rationale: у нас была проблема где приезжает пользовательский json небольшой (на пару-тройку кб) и рвет нам стек из-за глубины.
Со стороны rapidjson это проще всего поправить включив у них итеративный парсинг, который не будет использовать системный стек.
Но это не совсем все — с нашей стороны оно все развалится когда надо будет вызвать рекурсивно деструкторы TJsonValue — и тут уже можно будет покрутить MaxDepth.
Diffstat (limited to 'library/cpp/json/ut/json_reader_ut.cpp')
-rw-r--r-- | library/cpp/json/ut/json_reader_ut.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/library/cpp/json/ut/json_reader_ut.cpp b/library/cpp/json/ut/json_reader_ut.cpp index cd31afa0b8..115c85e1c7 100644 --- a/library/cpp/json/ut/json_reader_ut.cpp +++ b/library/cpp/json/ut/json_reader_ut.cpp @@ -66,6 +66,17 @@ public: } }; +void GenerateDeepJson(TStringStream& stream, ui64 depth) { + stream << "{\"key\":"; + for (ui32 i = 0; i < depth - 1; ++i) { + stream << "["; + } + for (ui32 i = 0; i < depth - 1; ++i) { + stream << "]"; + } + stream << "}"; +} + Y_UNIT_TEST_SUITE(TJsonReaderTest) { Y_UNIT_TEST(JsonReformatTest) { TString data = "{\"null value\": null, \"intkey\": 10, \"double key\": 11.11, \"string key\": \"string\", \"array\": [1,2,3,\"TString\"], \"bool key\": true}"; @@ -396,6 +407,44 @@ Y_UNIT_TEST_SUITE(TJsonReaderTest) { UNIT_ASSERT(v.GetMap().begin()->second.IsString()); UNIT_ASSERT_VALUES_EQUAL("", v.GetMap().begin()->second.GetString()); } + + // Parsing an extremely deep json tree would result in stack overflow. + // Not crashing on one is a good indicator of iterative mode. + Y_UNIT_TEST(TJsonIterativeTest) { + constexpr ui32 brackets = static_cast<ui32>(1e5); + + TStringStream jsonStream; + GenerateDeepJson(jsonStream, brackets); + + TJsonReaderConfig config; + config.UseIterativeParser = true; + config.MaxDepth = static_cast<ui32>(1e3); + + TJsonValue v; + UNIT_ASSERT(!ReadJsonTree(&jsonStream, &config, &v)); + } + + Y_UNIT_TEST(TJsonMaxDepthTest) { + constexpr ui32 depth = static_cast<ui32>(1e3); + + { + TStringStream jsonStream; + GenerateDeepJson(jsonStream, depth); + TJsonReaderConfig config; + config.MaxDepth = depth; + TJsonValue v; + UNIT_ASSERT(ReadJsonTree(&jsonStream, &config, &v)); + } + + { + TStringStream jsonStream; + GenerateDeepJson(jsonStream, depth); + TJsonReaderConfig config; + config.MaxDepth = depth - 1; + TJsonValue v; + UNIT_ASSERT(!ReadJsonTree(&jsonStream, &config, &v)); + } + } } |