From 1c4e8f5030afa016664e25018dcaf2cb58fd9c2e Mon Sep 17 00:00:00 2001 From: Piotr Sarna Date: Mon, 4 May 2020 17:45:01 +0200 Subject: [PATCH] alternator: fix checking max item depth Maximum item depth accepted by DynamoDB is 32, and alternator chose 39 as its arbitrary value in order to provide 7 shining new levels absolutely free of charge. Unfortunately, our code which checks the nesting level in rapidjson parsing bumps the counter by 2 for every object, which is due to rapidjson's internal implementation. In order to actually support at least 32 levels, the threshold is simply doubled. This commit comes with a test case which ensures that 32-nested items are accepted both by alternator and DynamoDB. The test case failed for alternator before the fix. Fixes #6366 Tests: unit(dev), alternator(local, remote) --- alternator/rjson.cc | 6 +++--- test/alternator/test_manual_requests.py | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/alternator/rjson.cc b/alternator/rjson.cc index cf726a117e..5de8e9f4eb 100644 --- a/alternator/rjson.cc +++ b/alternator/rjson.cc @@ -123,7 +123,7 @@ protected: std::string print(const rjson::value& value) { string_buffer buffer; - guarded_yieldable_json_handler writer(buffer, 39); + guarded_yieldable_json_handler writer(buffer, 78); value.Accept(writer); return std::string(buffer.GetString()); } @@ -133,7 +133,7 @@ rjson::value copy(const rjson::value& value) { } rjson::value parse(std::string_view str) { - guarded_yieldable_json_handler d(39); + guarded_yieldable_json_handler d(78); d.Parse(str.data(), str.size()); if (d.HasParseError()) { throw rjson::error(format("Parsing JSON failed: {}", GetParseError_En(d.GetParseError()))); @@ -143,7 +143,7 @@ rjson::value parse(std::string_view str) { } rjson::value parse_yieldable(std::string_view str) { - guarded_yieldable_json_handler d(39); + guarded_yieldable_json_handler d(78); d.Parse(str.data(), str.size()); if (d.HasParseError()) { throw rjson::error(format("Parsing JSON failed: {}", GetParseError_En(d.GetParseError()))); diff --git a/test/alternator/test_manual_requests.py b/test/alternator/test_manual_requests.py index c848aa265f..4920fa0cc4 100644 --- a/test/alternator/test_manual_requests.py +++ b/test/alternator/test_manual_requests.py @@ -81,6 +81,16 @@ def test_exceed_nested_level_a_little(dynamodb, test_table): with pytest.raises(ClientError, match='.*Exception.*nested'): test_table.put_item(Item={'p': p, 'c': c, 'nested': nested}) +# Test that we indeed allow the maximum level of 32 nested objects +def test_almost_exceed_nested_level(dynamodb, test_table): + p = 'xxx' + c = 'yyy' + nested = dict() + nested_it = nested + for i in range(30): # 30 added levels + top level + the item itself == 32 total + nested_it['a'] = dict() + nested_it = nested_it['a'] + test_table.put_item(Item={'p': p, 'c': c, 'nested': nested}) def test_too_large_request(dynamodb, test_table): p = 'abc'