blob: d254afc7cc92045efeddad090d74d19aa3d7e06d [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2017 The Chromium Authors
Jun Choi6d30c4a2017-12-09 01:10:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Adam Langleye0e46cdf2018-10-29 19:23:165#include "components/cbor/reader.h"
Jun Choi6d30c4a2017-12-09 01:10:326
7#include <math.h>
Jun Choi087c6d2d22018-01-22 22:54:188
Russ Hamilton385541b2023-07-06 00:30:389#include <limits>
Anastasiia Na63c5fb2021-11-19 15:11:3210#include <map>
Jun Choi07540c62017-12-21 02:51:4311#include <utility>
12
Russ Hamilton385541b2023-07-06 00:30:3813#include "base/bit_cast.h"
Hans Wennborgdf87046c2020-04-28 11:06:2414#include "base/check_op.h"
15#include "base/notreached.h"
Jun Choi06ae32d2017-12-21 18:52:3916#include "base/numerics/checked_math.h"
Jun Choi6d30c4a2017-12-09 01:10:3217#include "base/numerics/safe_conversions.h"
Jun Choi6d30c4a2017-12-09 01:10:3218#include "base/strings/string_util.h"
Adam Langleye0e46cdf2018-10-29 19:23:1619#include "components/cbor/constants.h"
Russ Hamilton385541b2023-07-06 00:30:3820#include "components/cbor/float_conversions.h"
Jun Choi6d30c4a2017-12-09 01:10:3221
Jun Choi9f1446c02017-12-21 23:33:2722namespace cbor {
Jun Choi6d30c4a2017-12-09 01:10:3223
Chris Palmerbe2d8dc2018-09-14 00:31:4224namespace constants {
25const char kUnsupportedMajorType[] = "Unsupported major type.";
26}
27
Jun Choi6d30c4a2017-12-09 01:10:3228namespace {
29
Adam Langleyb4f12f92018-10-26 21:00:0230Value::Type GetMajorType(uint8_t initial_data_byte) {
31 return static_cast<Value::Type>(
Jun Choi9f1446c02017-12-21 23:33:2732 (initial_data_byte & constants::kMajorTypeMask) >>
33 constants::kMajorTypeBitShift);
Jun Choi6d30c4a2017-12-09 01:10:3234}
35
36uint8_t GetAdditionalInfo(uint8_t initial_data_byte) {
Jun Choi9f1446c02017-12-21 23:33:2737 return initial_data_byte & constants::kAdditionalInformationMask;
Jun Choi6d30c4a2017-12-09 01:10:3238}
39
Chris Palmerbe2d8dc2018-09-14 00:31:4240// Error messages that correspond to each of the error codes. There is 1
Adam Langleye0e46cdf2018-10-29 19:23:1641// exception: we declare |kUnsupportedMajorType| in constants.h in the
Chris Palmerbe2d8dc2018-09-14 00:31:4242// `constants` namespace, because we use it in several files.
Jun Choi6d30c4a2017-12-09 01:10:3243const char kNoError[] = "Successfully deserialized to a CBOR value.";
Jun Choi6d30c4a2017-12-09 01:10:3244const char kUnknownAdditionalInfo[] =
45 "Unknown additional info format in the first byte.";
46const char kIncompleteCBORData[] =
47 "Prematurely terminated CBOR data byte array.";
48const char kIncorrectMapKeyType[] =
Kouhei Ueno2c9411e2018-02-02 00:41:0649 "Specified map key type is not supported by the current implementation.";
Jun Choi6d30c4a2017-12-09 01:10:3250const char kTooMuchNesting[] = "Too much nesting.";
Chris Palmer867100a2018-10-19 18:58:4651const char kInvalidUTF8[] =
52 "String encodings other than UTF-8 are not allowed.";
Jun Choi6d30c4a2017-12-09 01:10:3253const char kExtraneousData[] = "Trailing data bytes are not allowed.";
Jun Choi6d30c4a2017-12-09 01:10:3254const char kMapKeyOutOfOrder[] =
Adam Langley565f5a32018-04-02 22:53:4655 "Map keys must be strictly monotonically increasing based on byte length "
56 "and then by byte-wise lexical order.";
Jun Choi6d30c4a2017-12-09 01:10:3257const char kNonMinimalCBOREncoding[] =
58 "Unsigned integers must be encoded with minimum number of bytes.";
Jun Choi07540c62017-12-21 02:51:4359const char kUnsupportedSimpleValue[] =
60 "Unsupported or unassigned simple value.";
61const char kUnsupportedFloatingPointValue[] =
Russ Hamilton385541b2023-07-06 00:30:3862 "Floating point numbers are not supported unless the "
63 "`allow_floating_point` configuration option is set.";
Jun Choi06ae32d2017-12-21 18:52:3964const char kOutOfRangeIntegerValue[] =
65 "Integer values must be between INT64_MIN and INT64_MAX.";
Anastasiia Na63c5fb2021-11-19 15:11:3266const char kMapKeyDuplicate[] = "Duplicate map keys are not allowed.";
Adam Langleydc341a32018-04-04 17:23:4167const char kUnknownError[] = "An unknown error occured.";
Jun Choi6d30c4a2017-12-09 01:10:3268
69} // namespace
70
Adam Langley08718f732019-04-22 22:21:3371Reader::Config::Config() = default;
72Reader::Config::~Config() = default;
73
Adam Langleyb4f12f92018-10-26 21:00:0274Reader::Reader(base::span<const uint8_t> data)
David Benjaminf0023512018-08-29 22:30:0675 : rest_(data), error_code_(DecoderError::CBOR_NO_ERROR) {}
Sorin Jianuad029cb72024-10-04 03:35:5576Reader::~Reader() = default;
Jun Choi6d30c4a2017-12-09 01:10:3277
78// static
Arthur Sonzognic571efb2024-01-26 20:26:1879std::optional<Value> Reader::Read(base::span<uint8_t const> data,
80 DecoderError* error_code_out,
81 int max_nesting_level) {
Adam Langley08718f732019-04-22 22:21:3382 Config config;
83 config.error_code_out = error_code_out;
84 config.max_nesting_level = max_nesting_level;
Jun Choi6d30c4a2017-12-09 01:10:3285
Adam Langley08718f732019-04-22 22:21:3386 return Read(data, config);
Jun Choi6d30c4a2017-12-09 01:10:3287}
88
Kouhei Ueno7367cae62018-02-20 03:03:0989// static
Arthur Sonzognic571efb2024-01-26 20:26:1890std::optional<Value> Reader::Read(base::span<uint8_t const> data,
91 size_t* num_bytes_consumed,
92 DecoderError* error_code_out,
93 int max_nesting_level) {
Adam Langley08718f732019-04-22 22:21:3394 DCHECK(num_bytes_consumed);
95
96 Config config;
97 config.num_bytes_consumed = num_bytes_consumed;
98 config.error_code_out = error_code_out;
99 config.max_nesting_level = max_nesting_level;
100
101 return Read(data, config);
102}
103
104// static
Arthur Sonzognic571efb2024-01-26 20:26:18105std::optional<Value> Reader::Read(base::span<uint8_t const> data,
106 const Config& config) {
Adam Langleyb4f12f92018-10-26 21:00:02107 Reader reader(data);
Arthur Sonzognic571efb2024-01-26 20:26:18108 std::optional<Value> value =
Adam Langley08718f732019-04-22 22:21:33109 reader.DecodeCompleteDataItem(config, config.max_nesting_level);
Kouhei Ueno7367cae62018-02-20 03:03:09110
Chris Palmer867100a2018-10-19 18:58:46111 auto error = reader.GetErrorCode();
112 const bool success = value.has_value();
113 DCHECK_EQ(success, error == DecoderError::CBOR_NO_ERROR);
Adam Langleydc341a32018-04-04 17:23:41114
Adam Langley08718f732019-04-22 22:21:33115 if (config.num_bytes_consumed) {
116 *config.num_bytes_consumed =
117 success ? data.size() - reader.num_bytes_remaining() : 0;
118 } else if (success && reader.num_bytes_remaining() > 0) {
119 error = DecoderError::EXTRANEOUS_DATA;
120 value.reset();
Chris Palmer867100a2018-10-19 18:58:46121 }
Adam Langleydc341a32018-04-04 17:23:41122
Adam Langley08718f732019-04-22 22:21:33123 if (config.error_code_out) {
124 *config.error_code_out = error;
125 }
126
Chris Palmer867100a2018-10-19 18:58:46127 return value;
Kouhei Ueno7367cae62018-02-20 03:03:09128}
129
Arthur Sonzognic571efb2024-01-26 20:26:18130std::optional<Value> Reader::DecodeCompleteDataItem(const Config& config,
131 int max_nesting_level) {
Jun Choi6d30c4a2017-12-09 01:10:32132 if (max_nesting_level < 0 || max_nesting_level > kCBORMaxDepth) {
133 error_code_ = DecoderError::TOO_MUCH_NESTING;
Arthur Sonzognic571efb2024-01-26 20:26:18134 return std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32135 }
136
Arthur Sonzognic571efb2024-01-26 20:26:18137 std::optional<DataItemHeader> header = DecodeDataItemHeader();
Chris Palmer867100a2018-10-19 18:58:46138 if (!header.has_value()) {
Arthur Sonzognic571efb2024-01-26 20:26:18139 return std::nullopt;
Chris Palmer867100a2018-10-19 18:58:46140 }
Kouhei Ueno8abc3032018-02-20 05:36:19141
142 switch (header->type) {
Adam Langleyb4f12f92018-10-26 21:00:02143 case Value::Type::UNSIGNED:
Kouhei Ueno8abc3032018-02-20 05:36:19144 return DecodeValueToUnsigned(header->value);
Adam Langleyb4f12f92018-10-26 21:00:02145 case Value::Type::NEGATIVE:
Kouhei Ueno8abc3032018-02-20 05:36:19146 return DecodeValueToNegative(header->value);
Adam Langleyb4f12f92018-10-26 21:00:02147 case Value::Type::BYTE_STRING:
Kouhei Ueno8abc3032018-02-20 05:36:19148 return ReadByteStringContent(*header);
Adam Langleyb4f12f92018-10-26 21:00:02149 case Value::Type::STRING:
Adam Langley08718f732019-04-22 22:21:33150 return ReadStringContent(*header, config);
Adam Langleyb4f12f92018-10-26 21:00:02151 case Value::Type::ARRAY:
Adam Langley08718f732019-04-22 22:21:33152 return ReadArrayContent(*header, config, max_nesting_level);
Adam Langleyb4f12f92018-10-26 21:00:02153 case Value::Type::MAP:
Adam Langley08718f732019-04-22 22:21:33154 return ReadMapContent(*header, config, max_nesting_level);
Adam Langleyb4f12f92018-10-26 21:00:02155 case Value::Type::SIMPLE_VALUE:
Russ Hamilton385541b2023-07-06 00:30:38156 case Value::Type::FLOAT_VALUE:
157 // Floating point values also go here since they are also type 7.
158 return DecodeToSimpleValueOrFloat(*header, config);
Adam Langleyb4f12f92018-10-26 21:00:02159 case Value::Type::TAG: // We explicitly don't support TAG.
160 case Value::Type::NONE:
Adam Langley08718f732019-04-22 22:21:33161 case Value::Type::INVALID_UTF8:
Kouhei Ueno8abc3032018-02-20 05:36:19162 break;
163 }
164
165 error_code_ = DecoderError::UNSUPPORTED_MAJOR_TYPE;
Arthur Sonzognic571efb2024-01-26 20:26:18166 return std::nullopt;
Kouhei Ueno8abc3032018-02-20 05:36:19167}
168
Arthur Sonzognic571efb2024-01-26 20:26:18169std::optional<Reader::DataItemHeader> Reader::DecodeDataItemHeader() {
170 const std::optional<uint8_t> initial_byte = ReadByte();
David Benjaminf0023512018-08-29 22:30:06171 if (!initial_byte) {
Arthur Sonzognic571efb2024-01-26 20:26:18172 return std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32173 }
174
David Benjaminf0023512018-08-29 22:30:06175 const auto major_type = GetMajorType(initial_byte.value());
176 const uint8_t additional_info = GetAdditionalInfo(initial_byte.value());
Jun Choi6d30c4a2017-12-09 01:10:32177
Arthur Sonzognic571efb2024-01-26 20:26:18178 std::optional<uint64_t> value =
Russ Hamilton385541b2023-07-06 00:30:38179 ReadVariadicLengthInteger(major_type, additional_info);
Arthur Sonzognic571efb2024-01-26 20:26:18180 return value ? std::make_optional(
Chris Palmerbe2d8dc2018-09-14 00:31:42181 DataItemHeader{major_type, additional_info, value.value()})
Arthur Sonzognic571efb2024-01-26 20:26:18182 : std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32183}
184
Arthur Sonzognic571efb2024-01-26 20:26:18185std::optional<uint64_t> Reader::ReadVariadicLengthInteger(
Russ Hamilton385541b2023-07-06 00:30:38186 Value::Type type,
Chris Palmerbe2d8dc2018-09-14 00:31:42187 uint8_t additional_info) {
Jun Choi6d30c4a2017-12-09 01:10:32188 uint8_t additional_bytes = 0;
189 if (additional_info < 24) {
Arthur Sonzognic571efb2024-01-26 20:26:18190 return std::make_optional(additional_info);
Jun Choi6d30c4a2017-12-09 01:10:32191 } else if (additional_info == 24) {
192 additional_bytes = 1;
193 } else if (additional_info == 25) {
194 additional_bytes = 2;
195 } else if (additional_info == 26) {
196 additional_bytes = 4;
197 } else if (additional_info == 27) {
198 additional_bytes = 8;
199 } else {
200 error_code_ = DecoderError::UNKNOWN_ADDITIONAL_INFO;
Arthur Sonzognic571efb2024-01-26 20:26:18201 return std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32202 }
203
Arthur Sonzognic571efb2024-01-26 20:26:18204 const std::optional<base::span<const uint8_t>> bytes =
David Benjaminf0023512018-08-29 22:30:06205 ReadBytes(additional_bytes);
206 if (!bytes) {
Arthur Sonzognic571efb2024-01-26 20:26:18207 return std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32208 }
209
210 uint64_t int_data = 0;
David Benjaminf0023512018-08-29 22:30:06211 for (const uint8_t b : bytes.value()) {
Jun Choi6d30c4a2017-12-09 01:10:32212 int_data <<= 8;
David Benjaminf0023512018-08-29 22:30:06213 int_data |= b;
Jun Choi6d30c4a2017-12-09 01:10:32214 }
215
Russ Hamilton385541b2023-07-06 00:30:38216 if (type == Value::Type::SIMPLE_VALUE && additional_info >= 25 &&
217 additional_info <= 27) {
218 // This is a floating point value and so `additional_bytes` should not be
219 // treated as an integer by minimality checking.
Arthur Sonzognic571efb2024-01-26 20:26:18220 return std::make_optional(int_data);
Russ Hamilton385541b2023-07-06 00:30:38221 }
222
Chris Palmer867100a2018-10-19 18:58:46223 return IsEncodingMinimal(additional_bytes, int_data)
Arthur Sonzognic571efb2024-01-26 20:26:18224 ? std::make_optional(int_data)
225 : std::nullopt;
Jun Choi06ae32d2017-12-21 18:52:39226}
227
Arthur Sonzognic571efb2024-01-26 20:26:18228std::optional<Value> Reader::DecodeValueToNegative(uint64_t value) {
Jun Choi06ae32d2017-12-21 18:52:39229 auto negative_value = -base::CheckedNumeric<int64_t>(value) - 1;
230 if (!negative_value.IsValid()) {
231 error_code_ = DecoderError::OUT_OF_RANGE_INTEGER_VALUE;
Arthur Sonzognic571efb2024-01-26 20:26:18232 return std::nullopt;
Jun Choi06ae32d2017-12-21 18:52:39233 }
Russ Hamilton385541b2023-07-06 00:30:38234 return Value(static_cast<int64_t>(negative_value.ValueOrDie()));
Jun Choi06ae32d2017-12-21 18:52:39235}
236
Arthur Sonzognic571efb2024-01-26 20:26:18237std::optional<Value> Reader::DecodeValueToUnsigned(uint64_t value) {
Jun Choi06ae32d2017-12-21 18:52:39238 auto unsigned_value = base::CheckedNumeric<int64_t>(value);
239 if (!unsigned_value.IsValid()) {
240 error_code_ = DecoderError::OUT_OF_RANGE_INTEGER_VALUE;
Arthur Sonzognic571efb2024-01-26 20:26:18241 return std::nullopt;
Jun Choi06ae32d2017-12-21 18:52:39242 }
Russ Hamilton385541b2023-07-06 00:30:38243 return Value(static_cast<int64_t>(unsigned_value.ValueOrDie()));
Jun Choi6d30c4a2017-12-09 01:10:32244}
245
Arthur Sonzognic571efb2024-01-26 20:26:18246std::optional<Value> Reader::DecodeToSimpleValueOrFloat(
Russ Hamilton385541b2023-07-06 00:30:38247 const DataItemHeader& header,
248 const Config& config) {
Adam Langleybdc2b692018-04-05 15:24:04249 // ReadVariadicLengthInteger provides this bound.
250 CHECK_LE(header.additional_info, 27);
Russ Hamilton385541b2023-07-06 00:30:38251 // Floating point numbers.
Adam Langleybdc2b692018-04-05 15:24:04252 if (header.additional_info > 24) {
Russ Hamilton385541b2023-07-06 00:30:38253 if (header.additional_info >= 28) {
254 error_code_ = DecoderError::UNSUPPORTED_SIMPLE_VALUE;
Arthur Sonzognic571efb2024-01-26 20:26:18255 return std::nullopt;
Russ Hamilton385541b2023-07-06 00:30:38256 }
257 if (!config.allow_floating_point) {
258 error_code_ = DecoderError::UNSUPPORTED_FLOATING_POINT_VALUE;
Arthur Sonzognic571efb2024-01-26 20:26:18259 return std::nullopt;
Russ Hamilton385541b2023-07-06 00:30:38260 }
261
262 switch (header.additional_info) {
263 case 25:
264 return Value(DecodeHalfPrecisionFloat(header.value));
265 case 26: {
266 double result =
267 base::bit_cast<float>(static_cast<uint32_t>(header.value));
268 if (!std::isfinite(result) ||
269 result ==
270 DecodeHalfPrecisionFloat(EncodeHalfPrecisionFloat(result))) {
271 // This could have been encoded as a 16 bit float.
272 // Note that we use `isfinite()` here to handle NaN since infinity
273 // and NaN can both be encoded in 16 bits but NaN doesn't compare
274 // with equality.
275 error_code_ = DecoderError::NON_MINIMAL_CBOR_ENCODING;
Arthur Sonzognic571efb2024-01-26 20:26:18276 return std::nullopt;
Russ Hamilton385541b2023-07-06 00:30:38277 }
278 return Value(result);
279 }
280 case 27: {
281 double result = base::bit_cast<double>(header.value);
282 float result_32 = result;
283 if (result == result_32) {
284 // This could have been encoded as a 32 bit float.
285 error_code_ = DecoderError::NON_MINIMAL_CBOR_ENCODING;
Arthur Sonzognic571efb2024-01-26 20:26:18286 return std::nullopt;
Russ Hamilton385541b2023-07-06 00:30:38287 }
288 return Value(result);
289 }
290 default:
Peter Boström77d21352024-11-13 22:26:11291 NOTREACHED();
Russ Hamilton385541b2023-07-06 00:30:38292 }
Jun Choi07540c62017-12-21 02:51:43293 }
294
Adam Langleybdc2b692018-04-05 15:24:04295 // Since |header.additional_info| <= 24, ReadVariadicLengthInteger also
296 // provides this bound for |header.value|.
Kouhei Ueno8abc3032018-02-20 05:36:19297 CHECK_LE(header.value, 255u);
Adam Langleyccb62982018-04-05 17:44:46298 // |SimpleValue| is an enum class and so the underlying type is specified to
299 // be |int|. So this cast is safe.
Adam Langleyb4f12f92018-10-26 21:00:02300 Value::SimpleValue possibly_unsupported_simple_value =
301 static_cast<Value::SimpleValue>(static_cast<int>(header.value));
Jun Choi07540c62017-12-21 02:51:43302 switch (possibly_unsupported_simple_value) {
Adam Langleyb4f12f92018-10-26 21:00:02303 case Value::SimpleValue::FALSE_VALUE:
304 case Value::SimpleValue::TRUE_VALUE:
305 case Value::SimpleValue::NULL_VALUE:
306 case Value::SimpleValue::UNDEFINED:
307 return Value(possibly_unsupported_simple_value);
Jun Choi07540c62017-12-21 02:51:43308 }
309
310 error_code_ = DecoderError::UNSUPPORTED_SIMPLE_VALUE;
Arthur Sonzognic571efb2024-01-26 20:26:18311 return std::nullopt;
Jun Choi07540c62017-12-21 02:51:43312}
313
Arthur Sonzognic571efb2024-01-26 20:26:18314std::optional<Value> Reader::ReadStringContent(
Adam Langley08718f732019-04-22 22:21:33315 const Reader::DataItemHeader& header,
316 const Config& config) {
Kouhei Ueno8abc3032018-02-20 05:36:19317 uint64_t num_bytes = header.value;
Arthur Sonzognic571efb2024-01-26 20:26:18318 const std::optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
David Benjaminf0023512018-08-29 22:30:06319 if (!bytes) {
Arthur Sonzognic571efb2024-01-26 20:26:18320 return std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32321 }
322
David Benjaminf0023512018-08-29 22:30:06323 std::string cbor_string(bytes->begin(), bytes->end());
Adam Langley08718f732019-04-22 22:21:33324 if (base::IsStringUTF8(cbor_string)) {
325 return Value(std::move(cbor_string));
326 }
Jun Choi6d30c4a2017-12-09 01:10:32327
Adam Langley08718f732019-04-22 22:21:33328 if (config.allow_invalid_utf8) {
329 return Value(*bytes, Value::Type::INVALID_UTF8);
330 }
331
332 error_code_ = DecoderError::INVALID_UTF8;
Arthur Sonzognic571efb2024-01-26 20:26:18333 return std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32334}
335
Arthur Sonzognic571efb2024-01-26 20:26:18336std::optional<Value> Reader::ReadByteStringContent(
Adam Langleyb4f12f92018-10-26 21:00:02337 const Reader::DataItemHeader& header) {
Kouhei Ueno8abc3032018-02-20 05:36:19338 uint64_t num_bytes = header.value;
Arthur Sonzognic571efb2024-01-26 20:26:18339 const std::optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
David Benjaminf0023512018-08-29 22:30:06340 if (!bytes) {
Arthur Sonzognic571efb2024-01-26 20:26:18341 return std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32342 }
343
David Benjaminf0023512018-08-29 22:30:06344 std::vector<uint8_t> cbor_byte_string(bytes->begin(), bytes->end());
Adam Langleyb4f12f92018-10-26 21:00:02345 return Value(std::move(cbor_byte_string));
Jun Choi6d30c4a2017-12-09 01:10:32346}
347
Arthur Sonzognic571efb2024-01-26 20:26:18348std::optional<Value> Reader::ReadArrayContent(
Adam Langleyb4f12f92018-10-26 21:00:02349 const Reader::DataItemHeader& header,
Adam Langley08718f732019-04-22 22:21:33350 const Config& config,
Kouhei Ueno8abc3032018-02-20 05:36:19351 int max_nesting_level) {
Chris Palmer867100a2018-10-19 18:58:46352 const uint64_t length = header.value;
Kouhei Ueno1e313622018-02-22 07:37:27353
Adam Langleyb4f12f92018-10-26 21:00:02354 Value::ArrayValue cbor_array;
Kouhei Ueno1e313622018-02-22 07:37:27355 for (uint64_t i = 0; i < length; ++i) {
Arthur Sonzognic571efb2024-01-26 20:26:18356 std::optional<Value> cbor_element =
Adam Langley08718f732019-04-22 22:21:33357 DecodeCompleteDataItem(config, max_nesting_level - 1);
Chris Palmer867100a2018-10-19 18:58:46358 if (!cbor_element.has_value()) {
Arthur Sonzognic571efb2024-01-26 20:26:18359 return std::nullopt;
Chris Palmer867100a2018-10-19 18:58:46360 }
Jun Choi6d30c4a2017-12-09 01:10:32361 cbor_array.push_back(std::move(cbor_element.value()));
362 }
Adam Langleyb4f12f92018-10-26 21:00:02363 return Value(std::move(cbor_array));
Jun Choi6d30c4a2017-12-09 01:10:32364}
365
Arthur Sonzognic571efb2024-01-26 20:26:18366std::optional<Value> Reader::ReadMapContent(
Adam Langleyb4f12f92018-10-26 21:00:02367 const Reader::DataItemHeader& header,
Adam Langley08718f732019-04-22 22:21:33368 const Config& config,
Kouhei Ueno8abc3032018-02-20 05:36:19369 int max_nesting_level) {
Chris Palmer867100a2018-10-19 18:58:46370 const uint64_t length = header.value;
Kouhei Ueno1e313622018-02-22 07:37:27371
Anastasiia Na63c5fb2021-11-19 15:11:32372 std::map<Value, Value, Value::Less> cbor_map;
Kouhei Ueno1e313622018-02-22 07:37:27373 for (uint64_t i = 0; i < length; ++i) {
Arthur Sonzognic571efb2024-01-26 20:26:18374 std::optional<Value> key =
Adam Langley08718f732019-04-22 22:21:33375 DecodeCompleteDataItem(config, max_nesting_level - 1);
Arthur Sonzognic571efb2024-01-26 20:26:18376 std::optional<Value> value =
Adam Langley08718f732019-04-22 22:21:33377 DecodeCompleteDataItem(config, max_nesting_level - 1);
Chris Palmer867100a2018-10-19 18:58:46378 if (!key.has_value() || !value.has_value()) {
Arthur Sonzognic571efb2024-01-26 20:26:18379 return std::nullopt;
Chris Palmer867100a2018-10-19 18:58:46380 }
Jun Choi98a59e462017-12-14 23:04:09381
Kouhei Ueno2c9411e2018-02-02 00:41:06382 switch (key.value().type()) {
Adam Langleyb4f12f92018-10-26 21:00:02383 case Value::Type::UNSIGNED:
384 case Value::Type::NEGATIVE:
385 case Value::Type::STRING:
386 case Value::Type::BYTE_STRING:
Kouhei Ueno2c9411e2018-02-02 00:41:06387 break;
Adam Langley08718f732019-04-22 22:21:33388 case Value::Type::INVALID_UTF8:
389 error_code_ = DecoderError::INVALID_UTF8;
Arthur Sonzognic571efb2024-01-26 20:26:18390 return std::nullopt;
Kouhei Ueno2c9411e2018-02-02 00:41:06391 default:
392 error_code_ = DecoderError::INCORRECT_MAP_KEY_TYPE;
Arthur Sonzognic571efb2024-01-26 20:26:18393 return std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32394 }
Anastasiia Na63c5fb2021-11-19 15:11:32395 if (IsDuplicateKey(key.value(), cbor_map))
Arthur Sonzognic571efb2024-01-26 20:26:18396 return std::nullopt;
Anastasiia Na63c5fb2021-11-19 15:11:32397
398 if (!config.allow_and_canonicalize_out_of_order_keys &&
399 !IsKeyInOrder(key.value(), cbor_map)) {
Arthur Sonzognic571efb2024-01-26 20:26:18400 return std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32401 }
402
Anastasiia Na63c5fb2021-11-19 15:11:32403 cbor_map.emplace(std::move(key.value()), std::move(value.value()));
Jun Choi6d30c4a2017-12-09 01:10:32404 }
Anastasiia Na63c5fb2021-11-19 15:11:32405
406 Value::MapValue map;
407 map.reserve(cbor_map.size());
Alison Galeb8be9522024-04-16 00:00:31408 // TODO(crbug.com/40205788): when Chromium switches to C++17, this code can be
Anastasiia Na63c5fb2021-11-19 15:11:32409 // optimized using std::map::extract().
410 for (auto& it : cbor_map)
411 map.emplace_hint(map.end(), it.first.Clone(), std::move(it.second));
412 return Value(std::move(map));
Jun Choi6d30c4a2017-12-09 01:10:32413}
414
Arthur Sonzognic571efb2024-01-26 20:26:18415std::optional<uint8_t> Reader::ReadByte() {
416 const std::optional<base::span<const uint8_t>> bytes = ReadBytes(1);
417 return bytes ? std::make_optional(bytes.value()[0]) : std::nullopt;
David Benjaminf0023512018-08-29 22:30:06418}
419
Arthur Sonzognic571efb2024-01-26 20:26:18420std::optional<base::span<const uint8_t>> Reader::ReadBytes(uint64_t num_bytes) {
David Benjaminf0023512018-08-29 22:30:06421 if (base::strict_cast<uint64_t>(rest_.size()) < num_bytes) {
422 error_code_ = DecoderError::INCOMPLETE_CBOR_DATA;
Arthur Sonzognic571efb2024-01-26 20:26:18423 return std::nullopt;
Jun Choi6d30c4a2017-12-09 01:10:32424 }
Lukasz Anforowicz54cc8a22024-01-29 23:07:58425
426 // The `uint64_t` => `size_t` conversion below will always succeed
427 // because the `if` condition above implies that `num_bytes` fits into a
428 // `size_t`.
429 size_t size = base::checked_cast<size_t>(num_bytes);
430
431 const base::span<const uint8_t> ret = rest_.first(size);
432 rest_ = rest_.subspan(size);
David Benjaminf0023512018-08-29 22:30:06433 return ret;
Jun Choi6d30c4a2017-12-09 01:10:32434}
435
Adam Langleyb4f12f92018-10-26 21:00:02436bool Reader::IsEncodingMinimal(uint8_t additional_bytes, uint64_t uint_data) {
Jun Choi6d30c4a2017-12-09 01:10:32437 if ((additional_bytes == 1 && uint_data < 24) ||
438 uint_data <= (1ULL << 8 * (additional_bytes >> 1)) - 1) {
439 error_code_ = DecoderError::NON_MINIMAL_CBOR_ENCODING;
440 return false;
441 }
442 return true;
443}
444
Anastasiia Na63c5fb2021-11-19 15:11:32445bool Reader::IsKeyInOrder(const Value& new_key,
446 const std::map<Value, Value, Value::Less>& map) {
447 if (map.empty()) {
Adam Langley565f5a32018-04-02 22:53:46448 return true;
449 }
450
Anastasiia Na63c5fb2021-11-19 15:11:32451 const auto& max_current_key = map.rbegin()->first;
452 const auto less = map.key_comp();
Adam Langley565f5a32018-04-02 22:53:46453 if (!less(max_current_key, new_key)) {
Jun Choi6d30c4a2017-12-09 01:10:32454 error_code_ = DecoderError::OUT_OF_ORDER_KEY;
455 return false;
456 }
457 return true;
458}
459
Anastasiia Na63c5fb2021-11-19 15:11:32460bool Reader::IsDuplicateKey(const Value& new_key,
461 const std::map<Value, Value, Value::Less>& map) {
462 if (map.find(new_key) == map.end()) {
463 return false;
464 }
465 error_code_ = DecoderError::DUPLICATE_KEY;
466 return true;
467}
468
Jun Choi6d30c4a2017-12-09 01:10:32469// static
Adam Langleyb4f12f92018-10-26 21:00:02470const char* Reader::ErrorCodeToString(DecoderError error) {
Jun Choi6d30c4a2017-12-09 01:10:32471 switch (error) {
Daniel Bratell50fe9292017-12-11 15:18:54472 case DecoderError::CBOR_NO_ERROR:
Jun Choi6d30c4a2017-12-09 01:10:32473 return kNoError;
474 case DecoderError::UNSUPPORTED_MAJOR_TYPE:
Chris Palmerbe2d8dc2018-09-14 00:31:42475 return constants::kUnsupportedMajorType;
Jun Choi6d30c4a2017-12-09 01:10:32476 case DecoderError::UNKNOWN_ADDITIONAL_INFO:
477 return kUnknownAdditionalInfo;
478 case DecoderError::INCOMPLETE_CBOR_DATA:
479 return kIncompleteCBORData;
480 case DecoderError::INCORRECT_MAP_KEY_TYPE:
481 return kIncorrectMapKeyType;
482 case DecoderError::TOO_MUCH_NESTING:
483 return kTooMuchNesting;
484 case DecoderError::INVALID_UTF8:
485 return kInvalidUTF8;
486 case DecoderError::EXTRANEOUS_DATA:
487 return kExtraneousData;
Jun Choi6d30c4a2017-12-09 01:10:32488 case DecoderError::OUT_OF_ORDER_KEY:
489 return kMapKeyOutOfOrder;
490 case DecoderError::NON_MINIMAL_CBOR_ENCODING:
491 return kNonMinimalCBOREncoding;
Jun Choi07540c62017-12-21 02:51:43492 case DecoderError::UNSUPPORTED_SIMPLE_VALUE:
493 return kUnsupportedSimpleValue;
494 case DecoderError::UNSUPPORTED_FLOATING_POINT_VALUE:
495 return kUnsupportedFloatingPointValue;
Jun Choi06ae32d2017-12-21 18:52:39496 case DecoderError::OUT_OF_RANGE_INTEGER_VALUE:
497 return kOutOfRangeIntegerValue;
Anastasiia Na63c5fb2021-11-19 15:11:32498 case DecoderError::DUPLICATE_KEY:
499 return kMapKeyDuplicate;
Adam Langleydc341a32018-04-04 17:23:41500 case DecoderError::UNKNOWN_ERROR:
501 return kUnknownError;
Jun Choi6d30c4a2017-12-09 01:10:32502 default:
Peter Boström77d21352024-11-13 22:26:11503 NOTREACHED();
Jun Choi6d30c4a2017-12-09 01:10:32504 }
505}
506
Jun Choi9f1446c02017-12-21 23:33:27507} // namespace cbor