Commit 565f5a3f authored by Adam Langley's avatar Adam Langley Committed by Commit Bot

cbor: only need to check map value order.

If we enforce that each new map value is greater than the previous one
then that ensures that no duplicates are allowed without doing a lookup
for every insert.

Bug: 827551
Change-Id: Idcc24b1070cc1707362f37a7f76198053882148a
Reviewed-on: https://chromium-review.googlesource.com/982610
Commit-Queue: Adam Langley <agl@chromium.org>
Reviewed-by: default avatarBalazs Engedy <engedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547546}
parent b140562c
...@@ -40,10 +40,9 @@ const char kIncorrectMapKeyType[] = ...@@ -40,10 +40,9 @@ const char kIncorrectMapKeyType[] =
const char kTooMuchNesting[] = "Too much nesting."; const char kTooMuchNesting[] = "Too much nesting.";
const char kInvalidUTF8[] = "String encoding other than utf8 are not allowed."; const char kInvalidUTF8[] = "String encoding other than utf8 are not allowed.";
const char kExtraneousData[] = "Trailing data bytes are not allowed."; const char kExtraneousData[] = "Trailing data bytes are not allowed.";
const char kDuplicateKey[] = "Duplicate map keys are not allowed.";
const char kMapKeyOutOfOrder[] = const char kMapKeyOutOfOrder[] =
"Map keys must be sorted by byte length and then by byte-wise lexical " "Map keys must be strictly monotonically increasing based on byte length "
"order."; "and then by byte-wise lexical order.";
const char kNonMinimalCBOREncoding[] = const char kNonMinimalCBOREncoding[] =
"Unsigned integers must be encoded with minimum number of bytes."; "Unsigned integers must be encoded with minimum number of bytes.";
const char kUnsupportedSimpleValue[] = const char kUnsupportedSimpleValue[] =
...@@ -314,8 +313,7 @@ base::Optional<CBORValue> CBORReader::ReadMapContent( ...@@ -314,8 +313,7 @@ base::Optional<CBORValue> CBORReader::ReadMapContent(
error_code_ = DecoderError::INCORRECT_MAP_KEY_TYPE; error_code_ = DecoderError::INCORRECT_MAP_KEY_TYPE;
return base::nullopt; return base::nullopt;
} }
if (!CheckDuplicateKey(key.value(), &cbor_map) || if (!CheckOutOfOrderKey(key.value(), &cbor_map)) {
!CheckOutOfOrderKey(key.value(), &cbor_map)) {
return base::nullopt; return base::nullopt;
} }
...@@ -347,15 +345,6 @@ void CBORReader::CheckExtraneousData() { ...@@ -347,15 +345,6 @@ void CBORReader::CheckExtraneousData() {
error_code_ = DecoderError::EXTRANEOUS_DATA; error_code_ = DecoderError::EXTRANEOUS_DATA;
} }
bool CBORReader::CheckDuplicateKey(const CBORValue& new_key,
CBORValue::MapValue* map) {
if (base::ContainsKey(*map, new_key)) {
error_code_ = DecoderError::DUPLICATE_KEY;
return false;
}
return true;
}
bool CBORReader::HasValidUTF8Format(const std::string& string_data) { bool CBORReader::HasValidUTF8Format(const std::string& string_data) {
if (!base::IsStringUTF8(string_data)) { if (!base::IsStringUTF8(string_data)) {
error_code_ = DecoderError::INVALID_UTF8; error_code_ = DecoderError::INVALID_UTF8;
...@@ -366,8 +355,13 @@ bool CBORReader::HasValidUTF8Format(const std::string& string_data) { ...@@ -366,8 +355,13 @@ bool CBORReader::HasValidUTF8Format(const std::string& string_data) {
bool CBORReader::CheckOutOfOrderKey(const CBORValue& new_key, bool CBORReader::CheckOutOfOrderKey(const CBORValue& new_key,
CBORValue::MapValue* map) { CBORValue::MapValue* map) {
auto comparator = map->key_comp(); if (map->empty()) {
if (!map->empty() && comparator(new_key, map->rbegin()->first)) { return true;
}
const auto& max_current_key = map->rbegin()->first;
const auto less = map->key_comp();
if (!less(max_current_key, new_key)) {
error_code_ = DecoderError::OUT_OF_ORDER_KEY; error_code_ = DecoderError::OUT_OF_ORDER_KEY;
return false; return false;
} }
...@@ -397,8 +391,6 @@ const char* CBORReader::ErrorCodeToString(DecoderError error) { ...@@ -397,8 +391,6 @@ const char* CBORReader::ErrorCodeToString(DecoderError error) {
return kInvalidUTF8; return kInvalidUTF8;
case DecoderError::EXTRANEOUS_DATA: case DecoderError::EXTRANEOUS_DATA:
return kExtraneousData; return kExtraneousData;
case DecoderError::DUPLICATE_KEY:
return kDuplicateKey;
case DecoderError::OUT_OF_ORDER_KEY: case DecoderError::OUT_OF_ORDER_KEY:
return kMapKeyOutOfOrder; return kMapKeyOutOfOrder;
case DecoderError::NON_MINIMAL_CBOR_ENCODING: case DecoderError::NON_MINIMAL_CBOR_ENCODING:
......
...@@ -61,7 +61,6 @@ class CBOR_EXPORT CBORReader { ...@@ -61,7 +61,6 @@ class CBOR_EXPORT CBORReader {
TOO_MUCH_NESTING, TOO_MUCH_NESTING,
INVALID_UTF8, INVALID_UTF8,
EXTRANEOUS_DATA, EXTRANEOUS_DATA,
DUPLICATE_KEY,
OUT_OF_ORDER_KEY, OUT_OF_ORDER_KEY,
NON_MINIMAL_CBOR_ENCODING, NON_MINIMAL_CBOR_ENCODING,
UNSUPPORTED_SIMPLE_VALUE, UNSUPPORTED_SIMPLE_VALUE,
...@@ -142,7 +141,6 @@ class CBOR_EXPORT CBORReader { ...@@ -142,7 +141,6 @@ class CBOR_EXPORT CBORReader {
int max_nesting_level); int max_nesting_level);
bool CanConsume(uint64_t bytes); bool CanConsume(uint64_t bytes);
void CheckExtraneousData(); void CheckExtraneousData();
bool CheckDuplicateKey(const CBORValue& new_key, CBORValue::MapValue* map);
bool HasValidUTF8Format(const std::string& string_data); bool HasValidUTF8Format(const std::string& string_data);
bool CheckOutOfOrderKey(const CBORValue& new_key, CBORValue::MapValue* map); bool CheckOutOfOrderKey(const CBORValue& new_key, CBORValue::MapValue* map);
bool CheckMinimalEncoding(uint8_t additional_bytes, uint64_t uint_data); bool CheckMinimalEncoding(uint8_t additional_bytes, uint64_t uint_data);
......
...@@ -1207,7 +1207,7 @@ TEST(CBORReaderTest, TestDuplicateKeyError) { ...@@ -1207,7 +1207,7 @@ TEST(CBORReaderTest, TestDuplicateKeyError) {
base::Optional<CBORValue> cbor = base::Optional<CBORValue> cbor =
CBORReader::Read(kMapWithDuplicateKey, &error_code); CBORReader::Read(kMapWithDuplicateKey, &error_code);
EXPECT_FALSE(cbor.has_value()); EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, CBORReader::DecoderError::DUPLICATE_KEY); EXPECT_EQ(error_code, CBORReader::DecoderError::OUT_OF_ORDER_KEY);
} }
// Leveraging Markus Kuhn’s UTF-8 decoder stress test. See // Leveraging Markus Kuhn’s UTF-8 decoder stress test. See
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment