cbor.cc 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "cbor.h"
  5. #include <algorithm>
  6. #include <cassert>
  7. #include <cmath>
  8. #include <cstring>
  9. #include <limits>
  10. #include <stack>
  11. namespace crdtp {
  12. namespace cbor {
  13. namespace {
  14. // Indicates the number of bits the "initial byte" needs to be shifted to the
  15. // right after applying |kMajorTypeMask| to produce the major type in the
  16. // lowermost bits.
  17. static constexpr uint8_t kMajorTypeBitShift = 5u;
  18. // Mask selecting the low-order 5 bits of the "initial byte", which is where
  19. // the additional information is encoded.
  20. static constexpr uint8_t kAdditionalInformationMask = 0x1f;
  21. // Mask selecting the high-order 3 bits of the "initial byte", which indicates
  22. // the major type of the encoded value.
  23. static constexpr uint8_t kMajorTypeMask = 0xe0;
  24. // Indicates the integer is in the following byte.
  25. static constexpr uint8_t kAdditionalInformation1Byte = 24u;
  26. // Indicates the integer is in the next 2 bytes.
  27. static constexpr uint8_t kAdditionalInformation2Bytes = 25u;
  28. // Indicates the integer is in the next 4 bytes.
  29. static constexpr uint8_t kAdditionalInformation4Bytes = 26u;
  30. // Indicates the integer is in the next 8 bytes.
  31. static constexpr uint8_t kAdditionalInformation8Bytes = 27u;
  32. // Encodes the initial byte, consisting of the |type| in the first 3 bits
  33. // followed by 5 bits of |additional_info|.
  34. constexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) {
  35. return (static_cast<uint8_t>(type) << kMajorTypeBitShift) |
  36. (additional_info & kAdditionalInformationMask);
  37. }
  38. // TAG 24 indicates that what follows is a byte string which is
  39. // encoded in CBOR format. We use this as a wrapper for
  40. // maps and arrays, allowing us to skip them, because the
  41. // byte string carries its size (byte length).
  42. // https://tools.ietf.org/html/rfc7049#section-2.4.4.1
  43. static constexpr uint8_t kInitialByteForEnvelope =
  44. EncodeInitialByte(MajorType::TAG, kAdditionalInformation1Byte);
  45. // The standalone byte for "envelope" tag, to follow kInitialByteForEnvelope
  46. // in the correct implementation, as it is above in-tag value max (which is
  47. // also, confusingly, 24). See EnvelopeHeader::Parse() for more.
  48. static constexpr uint8_t kCBOREnvelopeTag = 24;
  49. // The initial byte for a byte string with at most 2^32 bytes
  50. // of payload. This is used for envelope encoding, even if
  51. // the byte string is shorter.
  52. static constexpr uint8_t kInitialByteFor32BitLengthByteString =
  53. EncodeInitialByte(MajorType::BYTE_STRING, 26);
  54. // See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional
  55. // info = 31.
  56. static constexpr uint8_t kInitialByteIndefiniteLengthArray =
  57. EncodeInitialByte(MajorType::ARRAY, 31);
  58. static constexpr uint8_t kInitialByteIndefiniteLengthMap =
  59. EncodeInitialByte(MajorType::MAP, 31);
  60. // See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite
  61. // length maps / arrays.
  62. static constexpr uint8_t kStopByte =
  63. EncodeInitialByte(MajorType::SIMPLE_VALUE, 31);
  64. // See RFC 7049 Section 2.3, Table 2.
  65. static constexpr uint8_t kEncodedTrue =
  66. EncodeInitialByte(MajorType::SIMPLE_VALUE, 21);
  67. static constexpr uint8_t kEncodedFalse =
  68. EncodeInitialByte(MajorType::SIMPLE_VALUE, 20);
  69. static constexpr uint8_t kEncodedNull =
  70. EncodeInitialByte(MajorType::SIMPLE_VALUE, 22);
  71. static constexpr uint8_t kInitialByteForDouble =
  72. EncodeInitialByte(MajorType::SIMPLE_VALUE, 27);
  73. // See RFC 7049 Table 3 and Section 2.4.4.2. This is used as a prefix for
  74. // arbitrary binary data encoded as BYTE_STRING.
  75. static constexpr uint8_t kExpectedConversionToBase64Tag =
  76. EncodeInitialByte(MajorType::TAG, 22);
  77. // Writes the bytes for |v| to |out|, starting with the most significant byte.
  78. // See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
  79. template <typename T>
  80. void WriteBytesMostSignificantByteFirst(T v, std::vector<uint8_t>* out) {
  81. for (int shift_bytes = sizeof(T) - 1; shift_bytes >= 0; --shift_bytes)
  82. out->push_back(0xff & (v >> (shift_bytes * 8)));
  83. }
  84. // Extracts sizeof(T) bytes from |in| to extract a value of type T
  85. // (e.g. uint64_t, uint32_t, ...), most significant byte first.
  86. // See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
  87. template <typename T>
  88. T ReadBytesMostSignificantByteFirst(span<uint8_t> in) {
  89. assert(in.size() >= sizeof(T));
  90. T result = 0;
  91. for (size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes)
  92. result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8);
  93. return result;
  94. }
  95. } // namespace
  96. namespace internals {
  97. // Reads the start of a token with definitive size from |bytes|.
  98. // |type| is the major type as specified in RFC 7049 Section 2.1.
  99. // |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
  100. // (e.g. for BYTE_STRING).
  101. // If successful, returns the number of bytes read. Otherwise returns 0.
  102. size_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
  103. if (bytes.empty())
  104. return 0;
  105. uint8_t initial_byte = bytes[0];
  106. *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift);
  107. uint8_t additional_information = initial_byte & kAdditionalInformationMask;
  108. if (additional_information < 24) {
  109. // Values 0-23 are encoded directly into the additional info of the
  110. // initial byte.
  111. *value = additional_information;
  112. return 1;
  113. }
  114. if (additional_information == kAdditionalInformation1Byte) {
  115. // Values 24-255 are encoded with one initial byte, followed by the value.
  116. if (bytes.size() < 2)
  117. return 0;
  118. *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1));
  119. return 2;
  120. }
  121. if (additional_information == kAdditionalInformation2Bytes) {
  122. // Values 256-65535: 1 initial byte + 2 bytes payload.
  123. if (bytes.size() < 1 + sizeof(uint16_t))
  124. return 0;
  125. *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1));
  126. return 3;
  127. }
  128. if (additional_information == kAdditionalInformation4Bytes) {
  129. // 32 bit uint: 1 initial byte + 4 bytes payload.
  130. if (bytes.size() < 1 + sizeof(uint32_t))
  131. return 0;
  132. *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1));
  133. return 5;
  134. }
  135. if (additional_information == kAdditionalInformation8Bytes) {
  136. // 64 bit uint: 1 initial byte + 8 bytes payload.
  137. if (bytes.size() < 1 + sizeof(uint64_t))
  138. return 0;
  139. *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1));
  140. return 9;
  141. }
  142. return 0;
  143. }
  144. // Writes the start of a token with |type|. The |value| may indicate the size,
  145. // or it may be the payload if the value is an unsigned integer.
  146. void WriteTokenStart(MajorType type,
  147. uint64_t value,
  148. std::vector<uint8_t>* encoded) {
  149. if (value < 24) {
  150. // Values 0-23 are encoded directly into the additional info of the
  151. // initial byte.
  152. encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value));
  153. return;
  154. }
  155. if (value <= std::numeric_limits<uint8_t>::max()) {
  156. // Values 24-255 are encoded with one initial byte, followed by the value.
  157. encoded->push_back(EncodeInitialByte(type, kAdditionalInformation1Byte));
  158. encoded->push_back(value);
  159. return;
  160. }
  161. if (value <= std::numeric_limits<uint16_t>::max()) {
  162. // Values 256-65535: 1 initial byte + 2 bytes payload.
  163. encoded->push_back(EncodeInitialByte(type, kAdditionalInformation2Bytes));
  164. WriteBytesMostSignificantByteFirst<uint16_t>(value, encoded);
  165. return;
  166. }
  167. if (value <= std::numeric_limits<uint32_t>::max()) {
  168. // 32 bit uint: 1 initial byte + 4 bytes payload.
  169. encoded->push_back(EncodeInitialByte(type, kAdditionalInformation4Bytes));
  170. WriteBytesMostSignificantByteFirst<uint32_t>(static_cast<uint32_t>(value),
  171. encoded);
  172. return;
  173. }
  174. // 64 bit uint: 1 initial byte + 8 bytes payload.
  175. encoded->push_back(EncodeInitialByte(type, kAdditionalInformation8Bytes));
  176. WriteBytesMostSignificantByteFirst<uint64_t>(value, encoded);
  177. }
  178. } // namespace internals
  179. // =============================================================================
  180. // Detecting CBOR content
  181. // =============================================================================
  182. bool IsCBORMessage(span<uint8_t> msg) {
  183. return msg.size() >= 4 && msg[0] == kInitialByteForEnvelope &&
  184. (msg[1] == kInitialByteFor32BitLengthByteString ||
  185. (msg[1] == kCBOREnvelopeTag &&
  186. msg[2] == kInitialByteFor32BitLengthByteString));
  187. }
  188. Status CheckCBORMessage(span<uint8_t> msg) {
  189. if (msg.empty())
  190. return Status(Error::CBOR_UNEXPECTED_EOF_IN_ENVELOPE, 0);
  191. if (msg[0] != kInitialByteForEnvelope)
  192. return Status(Error::CBOR_INVALID_START_BYTE, 0);
  193. StatusOr<EnvelopeHeader> status_or_header = EnvelopeHeader::Parse(msg);
  194. if (!status_or_header.ok())
  195. return status_or_header.status();
  196. const size_t pos = (*status_or_header).header_size();
  197. assert(pos < msg.size()); // EnvelopeParser would not allow empty envelope.
  198. if (msg[pos] != EncodeIndefiniteLengthMapStart())
  199. return Status(Error::CBOR_MAP_START_EXPECTED, pos);
  200. return Status();
  201. }
  202. // =============================================================================
  203. // Encoding invidiual CBOR items
  204. // =============================================================================
  205. uint8_t EncodeTrue() {
  206. return kEncodedTrue;
  207. }
  208. uint8_t EncodeFalse() {
  209. return kEncodedFalse;
  210. }
  211. uint8_t EncodeNull() {
  212. return kEncodedNull;
  213. }
  214. uint8_t EncodeIndefiniteLengthArrayStart() {
  215. return kInitialByteIndefiniteLengthArray;
  216. }
  217. uint8_t EncodeIndefiniteLengthMapStart() {
  218. return kInitialByteIndefiniteLengthMap;
  219. }
  220. uint8_t EncodeStop() {
  221. return kStopByte;
  222. }
  223. void EncodeInt32(int32_t value, std::vector<uint8_t>* out) {
  224. if (value >= 0) {
  225. internals::WriteTokenStart(MajorType::UNSIGNED, value, out);
  226. } else {
  227. uint64_t representation = static_cast<uint64_t>(-(value + 1));
  228. internals::WriteTokenStart(MajorType::NEGATIVE, representation, out);
  229. }
  230. }
  231. void EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out) {
  232. uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
  233. internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
  234. // When emitting UTF16 characters, we always write the least significant byte
  235. // first; this is because it's the native representation for X86.
  236. // TODO(johannes): Implement a more efficient thing here later, e.g.
  237. // casting *iff* the machine has this byte order.
  238. // The wire format for UTF16 chars will probably remain the same
  239. // (least significant byte first) since this way we can have
  240. // golden files, unittests, etc. that port easily and universally.
  241. // See also:
  242. // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
  243. for (const uint16_t two_bytes : in) {
  244. out->push_back(two_bytes);
  245. out->push_back(two_bytes >> 8);
  246. }
  247. }
  248. void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out) {
  249. internals::WriteTokenStart(MajorType::STRING,
  250. static_cast<uint64_t>(in.size_bytes()), out);
  251. out->insert(out->end(), in.begin(), in.end());
  252. }
  253. void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) {
  254. for (size_t ii = 0; ii < latin1.size(); ++ii) {
  255. if (latin1[ii] <= 127)
  256. continue;
  257. // If there's at least one non-ASCII char, convert to UTF8.
  258. std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii);
  259. for (; ii < latin1.size(); ++ii) {
  260. if (latin1[ii] <= 127) {
  261. utf8.push_back(latin1[ii]);
  262. } else {
  263. // 0xC0 means it's a UTF8 sequence with 2 bytes.
  264. utf8.push_back((latin1[ii] >> 6) | 0xc0);
  265. utf8.push_back((latin1[ii] | 0x80) & 0xbf);
  266. }
  267. }
  268. EncodeString8(SpanFrom(utf8), out);
  269. return;
  270. }
  271. EncodeString8(latin1, out);
  272. }
  273. void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) {
  274. // If there's at least one non-ASCII char, encode as STRING16 (UTF16).
  275. for (uint16_t ch : utf16) {
  276. if (ch <= 127)
  277. continue;
  278. EncodeString16(utf16, out);
  279. return;
  280. }
  281. // It's all US-ASCII, strip out every second byte and encode as UTF8.
  282. internals::WriteTokenStart(MajorType::STRING,
  283. static_cast<uint64_t>(utf16.size()), out);
  284. out->insert(out->end(), utf16.begin(), utf16.end());
  285. }
  286. void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) {
  287. out->push_back(kExpectedConversionToBase64Tag);
  288. uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
  289. internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
  290. out->insert(out->end(), in.begin(), in.end());
  291. }
  292. // A double is encoded with a specific initial byte
  293. // (kInitialByteForDouble) plus the 64 bits of payload for its value.
  294. constexpr size_t kEncodedDoubleSize = 1 + sizeof(uint64_t);
  295. void EncodeDouble(double value, std::vector<uint8_t>* out) {
  296. // The additional_info=27 indicates 64 bits for the double follow.
  297. // See RFC 7049 Section 2.3, Table 1.
  298. out->push_back(kInitialByteForDouble);
  299. union {
  300. double from_double;
  301. uint64_t to_uint64;
  302. } reinterpret;
  303. reinterpret.from_double = value;
  304. WriteBytesMostSignificantByteFirst<uint64_t>(reinterpret.to_uint64, out);
  305. }
  306. // =============================================================================
  307. // cbor::EnvelopeEncoder - for wrapping submessages
  308. // =============================================================================
  309. void EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) {
  310. assert(byte_size_pos_ == 0);
  311. out->push_back(kInitialByteForEnvelope);
  312. out->push_back(kCBOREnvelopeTag);
  313. out->push_back(kInitialByteFor32BitLengthByteString);
  314. byte_size_pos_ = out->size();
  315. out->resize(out->size() + sizeof(uint32_t));
  316. }
  317. bool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) {
  318. assert(byte_size_pos_ != 0);
  319. // The byte size is the size of the payload, that is, all the
  320. // bytes that were written past the byte size position itself.
  321. uint64_t byte_size = out->size() - (byte_size_pos_ + sizeof(uint32_t));
  322. // We store exactly 4 bytes, so at most INT32MAX, with most significant
  323. // byte first.
  324. if (byte_size > std::numeric_limits<uint32_t>::max())
  325. return false;
  326. for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0;
  327. --shift_bytes) {
  328. (*out)[byte_size_pos_++] = 0xff & (byte_size >> (shift_bytes * 8));
  329. }
  330. return true;
  331. }
  332. // static
  333. StatusOr<EnvelopeHeader> EnvelopeHeader::Parse(span<uint8_t> in) {
  334. auto header_or_status = ParseFromFragment(in);
  335. if (!header_or_status.ok())
  336. return header_or_status;
  337. if ((*header_or_status).outer_size() > in.size()) {
  338. return StatusOr<EnvelopeHeader>(
  339. Status(Error::CBOR_ENVELOPE_CONTENTS_LENGTH_MISMATCH, in.size()));
  340. }
  341. return header_or_status;
  342. }
  343. // static
  344. StatusOr<EnvelopeHeader> EnvelopeHeader::ParseFromFragment(span<uint8_t> in) {
  345. // Our copy of StatusOr<> requires explicit constructor.
  346. using Ret = StatusOr<EnvelopeHeader>;
  347. constexpr size_t kMinEnvelopeSize = 2 + /* for envelope tag */
  348. 1 + /* for byte string */
  349. 1; /* for contents, a map or an array */
  350. if (in.size() < kMinEnvelopeSize)
  351. return Ret(Status(Error::CBOR_UNEXPECTED_EOF_IN_ENVELOPE, in.size()));
  352. assert(in[0] == kInitialByteForEnvelope); // Caller should assure that.
  353. size_t offset = 1;
  354. // TODO(caseq): require this! We're currently accepting both a legacy,
  355. // non spec-compliant envelope tag (that this implementation still currently
  356. // produces), as well as a well-formed two-byte tag that a correct
  357. // implementation should emit.
  358. if (in[offset] == kCBOREnvelopeTag)
  359. ++offset;
  360. MajorType type;
  361. uint64_t size;
  362. size_t string_header_size =
  363. internals::ReadTokenStart(in.subspan(offset), &type, &size);
  364. if (!string_header_size)
  365. return Ret(Status(Error::CBOR_UNEXPECTED_EOF_IN_ENVELOPE, in.size()));
  366. if (type != MajorType::BYTE_STRING)
  367. return Ret(Status(Error::CBOR_INVALID_ENVELOPE, offset));
  368. // Do not allow empty envelopes -- at least an empty map/array should fit.
  369. if (!size) {
  370. return Ret(Status(Error::CBOR_MAP_OR_ARRAY_EXPECTED_IN_ENVELOPE,
  371. offset + string_header_size));
  372. }
  373. if (size > std::numeric_limits<uint32_t>::max())
  374. return Ret(Status(Error::CBOR_INVALID_ENVELOPE, offset));
  375. offset += string_header_size;
  376. return Ret(EnvelopeHeader(offset, static_cast<size_t>(size)));
  377. }
  378. // =============================================================================
  379. // cbor::NewCBOREncoder - for encoding from a streaming parser
  380. // =============================================================================
  381. namespace {
  382. class CBOREncoder : public ParserHandler {
  383. public:
  384. CBOREncoder(std::vector<uint8_t>* out, Status* status)
  385. : out_(out), status_(status) {
  386. *status_ = Status();
  387. }
  388. void HandleMapBegin() override {
  389. if (!status_->ok())
  390. return;
  391. envelopes_.emplace_back();
  392. envelopes_.back().EncodeStart(out_);
  393. out_->push_back(kInitialByteIndefiniteLengthMap);
  394. }
  395. void HandleMapEnd() override {
  396. if (!status_->ok())
  397. return;
  398. out_->push_back(kStopByte);
  399. assert(!envelopes_.empty());
  400. if (!envelopes_.back().EncodeStop(out_)) {
  401. HandleError(
  402. Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, out_->size()));
  403. return;
  404. }
  405. envelopes_.pop_back();
  406. }
  407. void HandleArrayBegin() override {
  408. if (!status_->ok())
  409. return;
  410. envelopes_.emplace_back();
  411. envelopes_.back().EncodeStart(out_);
  412. out_->push_back(kInitialByteIndefiniteLengthArray);
  413. }
  414. void HandleArrayEnd() override {
  415. if (!status_->ok())
  416. return;
  417. out_->push_back(kStopByte);
  418. assert(!envelopes_.empty());
  419. if (!envelopes_.back().EncodeStop(out_)) {
  420. HandleError(
  421. Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, out_->size()));
  422. return;
  423. }
  424. envelopes_.pop_back();
  425. }
  426. void HandleString8(span<uint8_t> chars) override {
  427. if (!status_->ok())
  428. return;
  429. EncodeString8(chars, out_);
  430. }
  431. void HandleString16(span<uint16_t> chars) override {
  432. if (!status_->ok())
  433. return;
  434. EncodeFromUTF16(chars, out_);
  435. }
  436. void HandleBinary(span<uint8_t> bytes) override {
  437. if (!status_->ok())
  438. return;
  439. EncodeBinary(bytes, out_);
  440. }
  441. void HandleDouble(double value) override {
  442. if (!status_->ok())
  443. return;
  444. EncodeDouble(value, out_);
  445. }
  446. void HandleInt32(int32_t value) override {
  447. if (!status_->ok())
  448. return;
  449. EncodeInt32(value, out_);
  450. }
  451. void HandleBool(bool value) override {
  452. if (!status_->ok())
  453. return;
  454. // See RFC 7049 Section 2.3, Table 2.
  455. out_->push_back(value ? kEncodedTrue : kEncodedFalse);
  456. }
  457. void HandleNull() override {
  458. if (!status_->ok())
  459. return;
  460. // See RFC 7049 Section 2.3, Table 2.
  461. out_->push_back(kEncodedNull);
  462. }
  463. void HandleError(Status error) override {
  464. if (!status_->ok())
  465. return;
  466. *status_ = error;
  467. out_->clear();
  468. }
  469. private:
  470. std::vector<uint8_t>* out_;
  471. std::vector<EnvelopeEncoder> envelopes_;
  472. Status* status_;
  473. };
  474. } // namespace
  475. std::unique_ptr<ParserHandler> NewCBOREncoder(std::vector<uint8_t>* out,
  476. Status* status) {
  477. return std::unique_ptr<ParserHandler>(new CBOREncoder(out, status));
  478. }
  479. // =============================================================================
  480. // cbor::CBORTokenizer - for parsing individual CBOR items
  481. // =============================================================================
  482. CBORTokenizer::CBORTokenizer(span<uint8_t> bytes)
  483. : bytes_(bytes), status_(Error::OK, 0) {
  484. ReadNextToken();
  485. }
  486. CBORTokenizer::~CBORTokenizer() {}
  487. CBORTokenTag CBORTokenizer::TokenTag() const {
  488. return token_tag_;
  489. }
  490. void CBORTokenizer::Next() {
  491. if (token_tag_ == CBORTokenTag::ERROR_VALUE ||
  492. token_tag_ == CBORTokenTag::DONE)
  493. return;
  494. ReadNextToken();
  495. }
  496. void CBORTokenizer::EnterEnvelope() {
  497. token_byte_length_ = GetEnvelopeHeader().header_size();
  498. ReadNextToken();
  499. }
  500. Status CBORTokenizer::Status() const {
  501. return status_;
  502. }
  503. // The following accessor functions ::GetInt32, ::GetDouble,
  504. // ::GetString8, ::GetString16WireRep, ::GetBinary, ::GetEnvelopeContents
  505. // assume that a particular token was recognized in ::ReadNextToken.
  506. // That's where all the error checking is done. By design,
  507. // the accessors (assuming the token was recognized) never produce
  508. // an error.
  509. int32_t CBORTokenizer::GetInt32() const {
  510. assert(token_tag_ == CBORTokenTag::INT32);
  511. // The range checks happen in ::ReadNextToken().
  512. return static_cast<int32_t>(
  513. token_start_type_ == MajorType::UNSIGNED
  514. ? token_start_internal_value_
  515. : -static_cast<int64_t>(token_start_internal_value_) - 1);
  516. }
  517. double CBORTokenizer::GetDouble() const {
  518. assert(token_tag_ == CBORTokenTag::DOUBLE);
  519. union {
  520. uint64_t from_uint64;
  521. double to_double;
  522. } reinterpret;
  523. reinterpret.from_uint64 = ReadBytesMostSignificantByteFirst<uint64_t>(
  524. bytes_.subspan(status_.pos + 1));
  525. return reinterpret.to_double;
  526. }
  527. span<uint8_t> CBORTokenizer::GetString8() const {
  528. assert(token_tag_ == CBORTokenTag::STRING8);
  529. auto length = static_cast<size_t>(token_start_internal_value_);
  530. return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
  531. }
  532. span<uint8_t> CBORTokenizer::GetString16WireRep() const {
  533. assert(token_tag_ == CBORTokenTag::STRING16);
  534. auto length = static_cast<size_t>(token_start_internal_value_);
  535. return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
  536. }
  537. span<uint8_t> CBORTokenizer::GetBinary() const {
  538. assert(token_tag_ == CBORTokenTag::BINARY);
  539. auto length = static_cast<size_t>(token_start_internal_value_);
  540. return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
  541. }
  542. span<uint8_t> CBORTokenizer::GetEnvelope() const {
  543. return bytes_.subspan(status_.pos, GetEnvelopeHeader().outer_size());
  544. }
  545. span<uint8_t> CBORTokenizer::GetEnvelopeContents() const {
  546. const EnvelopeHeader& header = GetEnvelopeHeader();
  547. return bytes_.subspan(status_.pos + header.header_size(),
  548. header.content_size());
  549. }
  550. const EnvelopeHeader& CBORTokenizer::GetEnvelopeHeader() const {
  551. assert(token_tag_ == CBORTokenTag::ENVELOPE);
  552. return envelope_header_;
  553. }
  554. // All error checking happens in ::ReadNextToken, so that the accessors
  555. // can avoid having to carry an error return value.
  556. //
  557. // With respect to checking the encoded lengths of strings, arrays, etc:
  558. // On the wire, CBOR uses 1,2,4, and 8 byte unsigned integers, so
  559. // we initially read them as uint64_t, usually into token_start_internal_value_.
  560. //
  561. // However, since these containers have a representation on the machine,
  562. // we need to do corresponding size computations on the input byte array,
  563. // output span (e.g. the payload for a string), etc., and size_t is
  564. // machine specific (in practice either 32 bit or 64 bit).
  565. //
  566. // Further, we must avoid overflowing size_t. Therefore, we use this
  567. // kMaxValidLength constant to:
  568. // - Reject values that are larger than the architecture specific
  569. // max size_t (differs between 32 bit and 64 bit arch).
  570. // - Reserve at least one bit so that we can check against overflows
  571. // when adding lengths (array / string length / etc.); we do this by
  572. // ensuring that the inputs to an addition are <= kMaxValidLength,
  573. // and then checking whether the sum went past it.
  574. //
  575. // See also
  576. // https://chromium.googlesource.com/chromium/src/+/main/docs/security/integer-semantics.md
  577. static const uint64_t kMaxValidLength =
  578. std::min<uint64_t>(std::numeric_limits<uint64_t>::max() >> 2,
  579. std::numeric_limits<size_t>::max());
  580. void CBORTokenizer::ReadNextToken() {
  581. status_.pos += token_byte_length_;
  582. status_.error = Error::OK;
  583. envelope_header_ = EnvelopeHeader();
  584. if (status_.pos >= bytes_.size()) {
  585. token_tag_ = CBORTokenTag::DONE;
  586. return;
  587. }
  588. const size_t remaining_bytes = bytes_.size() - status_.pos;
  589. switch (bytes_[status_.pos]) {
  590. case kStopByte:
  591. SetToken(CBORTokenTag::STOP, 1);
  592. return;
  593. case kInitialByteIndefiniteLengthMap:
  594. SetToken(CBORTokenTag::MAP_START, 1);
  595. return;
  596. case kInitialByteIndefiniteLengthArray:
  597. SetToken(CBORTokenTag::ARRAY_START, 1);
  598. return;
  599. case kEncodedTrue:
  600. SetToken(CBORTokenTag::TRUE_VALUE, 1);
  601. return;
  602. case kEncodedFalse:
  603. SetToken(CBORTokenTag::FALSE_VALUE, 1);
  604. return;
  605. case kEncodedNull:
  606. SetToken(CBORTokenTag::NULL_VALUE, 1);
  607. return;
  608. case kExpectedConversionToBase64Tag: { // BINARY
  609. const size_t bytes_read = internals::ReadTokenStart(
  610. bytes_.subspan(status_.pos + 1), &token_start_type_,
  611. &token_start_internal_value_);
  612. if (!bytes_read || token_start_type_ != MajorType::BYTE_STRING ||
  613. token_start_internal_value_ > kMaxValidLength) {
  614. SetError(Error::CBOR_INVALID_BINARY);
  615. return;
  616. }
  617. const uint64_t token_byte_length = token_start_internal_value_ +
  618. /* tag before token start: */ 1 +
  619. /* token start: */ bytes_read;
  620. if (token_byte_length > remaining_bytes) {
  621. SetError(Error::CBOR_INVALID_BINARY);
  622. return;
  623. }
  624. SetToken(CBORTokenTag::BINARY, static_cast<size_t>(token_byte_length));
  625. return;
  626. }
  627. case kInitialByteForDouble: { // DOUBLE
  628. if (kEncodedDoubleSize > remaining_bytes) {
  629. SetError(Error::CBOR_INVALID_DOUBLE);
  630. return;
  631. }
  632. SetToken(CBORTokenTag::DOUBLE, kEncodedDoubleSize);
  633. return;
  634. }
  635. case kInitialByteForEnvelope: { // ENVELOPE
  636. StatusOr<EnvelopeHeader> status_or_header =
  637. EnvelopeHeader::Parse(bytes_.subspan(status_.pos));
  638. if (!status_or_header.ok()) {
  639. status_.pos += status_or_header.status().pos;
  640. SetError(status_or_header.status().error);
  641. return;
  642. }
  643. assert((*status_or_header).outer_size() <= remaining_bytes);
  644. envelope_header_ = *status_or_header;
  645. SetToken(CBORTokenTag::ENVELOPE, envelope_header_.outer_size());
  646. return;
  647. }
  648. default: {
  649. const size_t bytes_read = internals::ReadTokenStart(
  650. bytes_.subspan(status_.pos), &token_start_type_,
  651. &token_start_internal_value_);
  652. switch (token_start_type_) {
  653. case MajorType::UNSIGNED: // INT32.
  654. // INT32 is a signed int32 (int32 makes sense for the
  655. // inspector protocol, it's not a CBOR limitation), so we check
  656. // against the signed max, so that the allowable values are
  657. // 0, 1, 2, ... 2^31 - 1.
  658. if (!bytes_read ||
  659. static_cast<uint64_t>(std::numeric_limits<int32_t>::max()) <
  660. static_cast<uint64_t>(token_start_internal_value_)) {
  661. SetError(Error::CBOR_INVALID_INT32);
  662. return;
  663. }
  664. SetToken(CBORTokenTag::INT32, bytes_read);
  665. return;
  666. case MajorType::NEGATIVE: { // INT32.
  667. // INT32 is a signed int32 (int32 makes sense for the
  668. // inspector protocol, it's not a CBOR limitation); in CBOR, the
  669. // negative values for INT32 are represented as NEGATIVE, that is, -1
  670. // INT32 is represented as 1 << 5 | 0 (major type 1, additional info
  671. // value 0).
  672. // The represented allowed values range is -1 to -2^31.
  673. // They are mapped into the encoded range of 0 to 2^31-1.
  674. // We check the payload in token_start_internal_value_ against
  675. // that range (2^31-1 is also known as
  676. // std::numeric_limits<int32_t>::max()).
  677. if (!bytes_read ||
  678. static_cast<uint64_t>(token_start_internal_value_) >
  679. static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
  680. SetError(Error::CBOR_INVALID_INT32);
  681. return;
  682. }
  683. SetToken(CBORTokenTag::INT32, bytes_read);
  684. return;
  685. }
  686. case MajorType::STRING: { // STRING8.
  687. if (!bytes_read || token_start_internal_value_ > kMaxValidLength) {
  688. SetError(Error::CBOR_INVALID_STRING8);
  689. return;
  690. }
  691. uint64_t token_byte_length = token_start_internal_value_ + bytes_read;
  692. if (token_byte_length > remaining_bytes) {
  693. SetError(Error::CBOR_INVALID_STRING8);
  694. return;
  695. }
  696. SetToken(CBORTokenTag::STRING8,
  697. static_cast<size_t>(token_byte_length));
  698. return;
  699. }
  700. case MajorType::BYTE_STRING: { // STRING16.
  701. // Length must be divisible by 2 since UTF16 is 2 bytes per
  702. // character, hence the &1 check.
  703. if (!bytes_read || token_start_internal_value_ > kMaxValidLength ||
  704. token_start_internal_value_ & 1) {
  705. SetError(Error::CBOR_INVALID_STRING16);
  706. return;
  707. }
  708. uint64_t token_byte_length = token_start_internal_value_ + bytes_read;
  709. if (token_byte_length > remaining_bytes) {
  710. SetError(Error::CBOR_INVALID_STRING16);
  711. return;
  712. }
  713. SetToken(CBORTokenTag::STRING16,
  714. static_cast<size_t>(token_byte_length));
  715. return;
  716. }
  717. case MajorType::ARRAY:
  718. case MajorType::MAP:
  719. case MajorType::TAG:
  720. case MajorType::SIMPLE_VALUE:
  721. SetError(Error::CBOR_UNSUPPORTED_VALUE);
  722. return;
  723. }
  724. }
  725. }
  726. }
  727. void CBORTokenizer::SetToken(CBORTokenTag token_tag, size_t token_byte_length) {
  728. token_tag_ = token_tag;
  729. token_byte_length_ = token_byte_length;
  730. }
  731. void CBORTokenizer::SetError(Error error) {
  732. token_tag_ = CBORTokenTag::ERROR_VALUE;
  733. status_.error = error;
  734. }
  735. // =============================================================================
  736. // cbor::ParseCBOR - for receiving streaming parser events for CBOR messages
  737. // =============================================================================
  738. namespace {
  739. // When parsing CBOR, we limit recursion depth for objects and arrays
  740. // to this constant.
  741. static constexpr int kStackLimit = 300;
  742. // Below are three parsing routines for CBOR, which cover enough
  743. // to roundtrip JSON messages.
  744. bool ParseMap(int32_t stack_depth,
  745. CBORTokenizer* tokenizer,
  746. ParserHandler* out);
  747. bool ParseArray(int32_t stack_depth,
  748. CBORTokenizer* tokenizer,
  749. ParserHandler* out);
  750. bool ParseValue(int32_t stack_depth,
  751. CBORTokenizer* tokenizer,
  752. ParserHandler* out);
  753. void ParseUTF16String(CBORTokenizer* tokenizer, ParserHandler* out) {
  754. std::vector<uint16_t> value;
  755. span<uint8_t> rep = tokenizer->GetString16WireRep();
  756. for (size_t ii = 0; ii < rep.size(); ii += 2)
  757. value.push_back((rep[ii + 1] << 8) | rep[ii]);
  758. out->HandleString16(span<uint16_t>(value.data(), value.size()));
  759. tokenizer->Next();
  760. }
  761. bool ParseUTF8String(CBORTokenizer* tokenizer, ParserHandler* out) {
  762. assert(tokenizer->TokenTag() == CBORTokenTag::STRING8);
  763. out->HandleString8(tokenizer->GetString8());
  764. tokenizer->Next();
  765. return true;
  766. }
  767. bool ParseEnvelope(int32_t stack_depth,
  768. CBORTokenizer* tokenizer,
  769. ParserHandler* out) {
  770. assert(tokenizer->TokenTag() == CBORTokenTag::ENVELOPE);
  771. // Before we enter the envelope, we save the position that we
  772. // expect to see after we're done parsing the envelope contents.
  773. // This way we can compare and produce an error if the contents
  774. // didn't fit exactly into the envelope length.
  775. size_t pos_past_envelope =
  776. tokenizer->Status().pos + tokenizer->GetEnvelopeHeader().outer_size();
  777. tokenizer->EnterEnvelope();
  778. switch (tokenizer->TokenTag()) {
  779. case CBORTokenTag::ERROR_VALUE:
  780. out->HandleError(tokenizer->Status());
  781. return false;
  782. case CBORTokenTag::MAP_START:
  783. if (!ParseMap(stack_depth + 1, tokenizer, out))
  784. return false;
  785. break; // Continue to check pos_past_envelope below.
  786. case CBORTokenTag::ARRAY_START:
  787. if (!ParseArray(stack_depth + 1, tokenizer, out))
  788. return false;
  789. break; // Continue to check pos_past_envelope below.
  790. default:
  791. out->HandleError(Status{Error::CBOR_MAP_OR_ARRAY_EXPECTED_IN_ENVELOPE,
  792. tokenizer->Status().pos});
  793. return false;
  794. }
  795. // The contents of the envelope parsed OK, now check that we're at
  796. // the expected position.
  797. if (pos_past_envelope != tokenizer->Status().pos) {
  798. out->HandleError(Status{Error::CBOR_ENVELOPE_CONTENTS_LENGTH_MISMATCH,
  799. tokenizer->Status().pos});
  800. return false;
  801. }
  802. return true;
  803. }
  804. bool ParseValue(int32_t stack_depth,
  805. CBORTokenizer* tokenizer,
  806. ParserHandler* out) {
  807. if (stack_depth > kStackLimit) {
  808. out->HandleError(
  809. Status{Error::CBOR_STACK_LIMIT_EXCEEDED, tokenizer->Status().pos});
  810. return false;
  811. }
  812. switch (tokenizer->TokenTag()) {
  813. case CBORTokenTag::ERROR_VALUE:
  814. out->HandleError(tokenizer->Status());
  815. return false;
  816. case CBORTokenTag::DONE:
  817. out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE,
  818. tokenizer->Status().pos});
  819. return false;
  820. case CBORTokenTag::ENVELOPE:
  821. return ParseEnvelope(stack_depth, tokenizer, out);
  822. case CBORTokenTag::TRUE_VALUE:
  823. out->HandleBool(true);
  824. tokenizer->Next();
  825. return true;
  826. case CBORTokenTag::FALSE_VALUE:
  827. out->HandleBool(false);
  828. tokenizer->Next();
  829. return true;
  830. case CBORTokenTag::NULL_VALUE:
  831. out->HandleNull();
  832. tokenizer->Next();
  833. return true;
  834. case CBORTokenTag::INT32:
  835. out->HandleInt32(tokenizer->GetInt32());
  836. tokenizer->Next();
  837. return true;
  838. case CBORTokenTag::DOUBLE:
  839. out->HandleDouble(tokenizer->GetDouble());
  840. tokenizer->Next();
  841. return true;
  842. case CBORTokenTag::STRING8:
  843. return ParseUTF8String(tokenizer, out);
  844. case CBORTokenTag::STRING16:
  845. ParseUTF16String(tokenizer, out);
  846. return true;
  847. case CBORTokenTag::BINARY: {
  848. out->HandleBinary(tokenizer->GetBinary());
  849. tokenizer->Next();
  850. return true;
  851. }
  852. case CBORTokenTag::MAP_START:
  853. return ParseMap(stack_depth + 1, tokenizer, out);
  854. case CBORTokenTag::ARRAY_START:
  855. return ParseArray(stack_depth + 1, tokenizer, out);
  856. default:
  857. out->HandleError(
  858. Status{Error::CBOR_UNSUPPORTED_VALUE, tokenizer->Status().pos});
  859. return false;
  860. }
  861. }
  862. // |bytes| must start with the indefinite length array byte, so basically,
  863. // ParseArray may only be called after an indefinite length array has been
  864. // detected.
  865. bool ParseArray(int32_t stack_depth,
  866. CBORTokenizer* tokenizer,
  867. ParserHandler* out) {
  868. assert(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START);
  869. tokenizer->Next();
  870. out->HandleArrayBegin();
  871. while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
  872. if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
  873. out->HandleError(
  874. Status{Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, tokenizer->Status().pos});
  875. return false;
  876. }
  877. if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
  878. out->HandleError(tokenizer->Status());
  879. return false;
  880. }
  881. // Parse value.
  882. if (!ParseValue(stack_depth, tokenizer, out))
  883. return false;
  884. }
  885. out->HandleArrayEnd();
  886. tokenizer->Next();
  887. return true;
  888. }
  889. // |bytes| must start with the indefinite length array byte, so basically,
  890. // ParseArray may only be called after an indefinite length array has been
  891. // detected.
  892. bool ParseMap(int32_t stack_depth,
  893. CBORTokenizer* tokenizer,
  894. ParserHandler* out) {
  895. assert(tokenizer->TokenTag() == CBORTokenTag::MAP_START);
  896. out->HandleMapBegin();
  897. tokenizer->Next();
  898. while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
  899. if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
  900. out->HandleError(
  901. Status{Error::CBOR_UNEXPECTED_EOF_IN_MAP, tokenizer->Status().pos});
  902. return false;
  903. }
  904. if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
  905. out->HandleError(tokenizer->Status());
  906. return false;
  907. }
  908. // Parse key.
  909. if (tokenizer->TokenTag() == CBORTokenTag::STRING8) {
  910. if (!ParseUTF8String(tokenizer, out))
  911. return false;
  912. } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) {
  913. ParseUTF16String(tokenizer, out);
  914. } else {
  915. out->HandleError(
  916. Status{Error::CBOR_INVALID_MAP_KEY, tokenizer->Status().pos});
  917. return false;
  918. }
  919. // Parse value.
  920. if (!ParseValue(stack_depth, tokenizer, out))
  921. return false;
  922. }
  923. out->HandleMapEnd();
  924. tokenizer->Next();
  925. return true;
  926. }
  927. } // namespace
  928. void ParseCBOR(span<uint8_t> bytes, ParserHandler* out) {
  929. if (bytes.empty()) {
  930. out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_IN_ENVELOPE, 0});
  931. return;
  932. }
  933. CBORTokenizer tokenizer(bytes);
  934. if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
  935. out->HandleError(tokenizer.Status());
  936. return;
  937. }
  938. if (!ParseValue(/*stack_depth=*/0, &tokenizer, out))
  939. return;
  940. if (tokenizer.TokenTag() == CBORTokenTag::DONE)
  941. return;
  942. if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
  943. out->HandleError(tokenizer.Status());
  944. return;
  945. }
  946. out->HandleError(Status{Error::CBOR_TRAILING_JUNK, tokenizer.Status().pos});
  947. }
  948. // =============================================================================
  949. // cbor::AppendString8EntryToMap - for limited in-place editing of messages
  950. // =============================================================================
  951. Status AppendString8EntryToCBORMap(span<uint8_t> string8_key,
  952. span<uint8_t> string8_value,
  953. std::vector<uint8_t>* cbor) {
  954. span<uint8_t> bytes(cbor->data(), cbor->size());
  955. CBORTokenizer tokenizer(bytes);
  956. if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE)
  957. return tokenizer.Status();
  958. if (tokenizer.TokenTag() != CBORTokenTag::ENVELOPE)
  959. return Status(Error::CBOR_INVALID_ENVELOPE, 0);
  960. EnvelopeHeader env_header = tokenizer.GetEnvelopeHeader();
  961. size_t old_size = cbor->size();
  962. if (old_size != env_header.outer_size())
  963. return Status(Error::CBOR_INVALID_ENVELOPE, 0);
  964. assert(env_header.content_size() > 0);
  965. if (tokenizer.GetEnvelopeContents()[0] != EncodeIndefiniteLengthMapStart())
  966. return Status(Error::CBOR_MAP_START_EXPECTED, env_header.header_size());
  967. if (bytes[bytes.size() - 1] != EncodeStop())
  968. return Status(Error::CBOR_MAP_STOP_EXPECTED, cbor->size() - 1);
  969. // We generally accept envelope headers with size specified in all possible
  970. // widths, but when it comes to modifying, we only support the fixed 4 byte
  971. // widths that we produce.
  972. const size_t byte_string_pos = bytes[1] == kCBOREnvelopeTag ? 2 : 1;
  973. if (bytes[byte_string_pos] != kInitialByteFor32BitLengthByteString)
  974. return Status(Error::CBOR_INVALID_ENVELOPE, byte_string_pos);
  975. cbor->pop_back();
  976. EncodeString8(string8_key, cbor);
  977. EncodeString8(string8_value, cbor);
  978. cbor->push_back(EncodeStop());
  979. size_t new_envelope_size =
  980. env_header.content_size() + (cbor->size() - old_size);
  981. if (new_envelope_size > std::numeric_limits<uint32_t>::max())
  982. return Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, 0);
  983. std::vector<uint8_t>::iterator out =
  984. cbor->begin() + env_header.header_size() - sizeof(int32_t);
  985. *(out++) = (new_envelope_size >> 24) & 0xff;
  986. *(out++) = (new_envelope_size >> 16) & 0xff;
  987. *(out++) = (new_envelope_size >> 8) & 0xff;
  988. *(out) = new_envelope_size & 0xff;
  989. return Status();
  990. }
  991. } // namespace cbor
  992. } // namespace crdtp