diff options
| author | ionagamed <[email protected]> | 2023-11-29 08:16:34 +0300 | 
|---|---|---|
| committer | ionagamed <[email protected]> | 2023-11-29 08:51:03 +0300 | 
| commit | 55fc158d4d2d8ae4d9f026e1afac03c7daae294d (patch) | |
| tree | bff2aa2edeae94bbf21a7a9875c6d8a1cbe8974c /library/cpp/json/ut | |
| parent | 4c48882379d93a43bd74060add09e309ce5e5002 (diff) | |
library/json: add MaxDepth and iterative parsing into config
rationale: у нас была проблема где приезжает пользовательский json небольшой (на пару-тройку кб) и рвет нам стек из-за глубины.
Со стороны rapidjson это проще всего поправить включив у них итеративный парсинг, который не будет использовать системный стек.
Но это не совсем все — с нашей стороны оно все развалится когда надо будет вызвать рекурсивно деструкторы TJsonValue — и тут уже можно будет покрутить MaxDepth.
Diffstat (limited to 'library/cpp/json/ut')
| -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 cd31afa0b8b..115c85e1c7e 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)); +        } +    }  }  | 
