Commit b179dd83 authored by Johannes Henkel's avatar Johannes Henkel Committed by Commit Bot

[DevTools] Roll inspector_protocol.

New revision: e8ba1a7665bdcd8336915d5ca4b390e0cf6b1f6f

Change-Id: I6a916f003a29b0b9436ad031bbd43eddfa189e63
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1634938
Auto-Submit: Johannes Henkel <johannes@chromium.org>
Reviewed-by: 's avatarAlexei Filippov <alph@chromium.org>
Commit-Queue: Alexei Filippov <alph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61923}
parent 211b4e54
...@@ -2,7 +2,7 @@ Name: inspector protocol ...@@ -2,7 +2,7 @@ Name: inspector protocol
Short Name: inspector_protocol Short Name: inspector_protocol
URL: https://chromium.googlesource.com/deps/inspector_protocol/ URL: https://chromium.googlesource.com/deps/inspector_protocol/
Version: 0 Version: 0
Revision: fe0467fd105a9ea90fbb091dc2a7b4cdbf539803 Revision: e8ba1a7665bdcd8336915d5ca4b390e0cf6b1f6f
License: BSD License: BSD
License File: LICENSE License File: LICENSE
Security Critical: no Security Critical: no
......
...@@ -101,6 +101,17 @@ def read_config(): ...@@ -101,6 +101,17 @@ def read_config():
".lib": False, ".lib": False,
".lib.export_macro": "", ".lib.export_macro": "",
".lib.export_header": False, ".lib.export_header": False,
# The encoding lib consists of encoding/encoding.h and
# encoding/encoding.cc in its subdirectory, which binaries
# may link / depend on, instead of relying on the
# JINJA2 templates lib/encoding_{h,cc}.template.
# In that case, |header| identifies the include file
# and |namespace| is the namespace it's using. Usually
# inspector_protocol_encoding but for v8's copy it's
# v8_inspector_protocol_encoding.
# TODO(johannes): Migrate away from lib/encoding_{h,cc}.template
# in favor of this.
".encoding_lib": { "header": "", "namespace": []},
} }
for key_value in config_values: for key_value in config_values:
parts = key_value.split("=") parts = key_value.split("=")
......
...@@ -185,11 +185,10 @@ namespace internals { ...@@ -185,11 +185,10 @@ namespace internals {
// |type| is the major type as specified in RFC 7049 Section 2.1. // |type| is the major type as specified in RFC 7049 Section 2.1.
// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size // |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
// (e.g. for BYTE_STRING). // (e.g. for BYTE_STRING).
// If successful, returns the number of bytes read. Otherwise returns -1. // If successful, returns the number of bytes read. Otherwise returns 0.
// TODO(johannes): change return type to size_t and use 0 for error. size_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
if (bytes.empty()) if (bytes.empty())
return -1; return 0;
uint8_t initial_byte = bytes[0]; uint8_t initial_byte = bytes[0];
*type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift); *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift);
...@@ -203,32 +202,32 @@ int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) { ...@@ -203,32 +202,32 @@ int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
if (additional_information == kAdditionalInformation1Byte) { if (additional_information == kAdditionalInformation1Byte) {
// Values 24-255 are encoded with one initial byte, followed by the value. // Values 24-255 are encoded with one initial byte, followed by the value.
if (bytes.size() < 2) if (bytes.size() < 2)
return -1; return 0;
*value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1)); *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1));
return 2; return 2;
} }
if (additional_information == kAdditionalInformation2Bytes) { if (additional_information == kAdditionalInformation2Bytes) {
// Values 256-65535: 1 initial byte + 2 bytes payload. // Values 256-65535: 1 initial byte + 2 bytes payload.
if (bytes.size() < 1 + sizeof(uint16_t)) if (bytes.size() < 1 + sizeof(uint16_t))
return -1; return 0;
*value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1)); *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1));
return 3; return 3;
} }
if (additional_information == kAdditionalInformation4Bytes) { if (additional_information == kAdditionalInformation4Bytes) {
// 32 bit uint: 1 initial byte + 4 bytes payload. // 32 bit uint: 1 initial byte + 4 bytes payload.
if (bytes.size() < 1 + sizeof(uint32_t)) if (bytes.size() < 1 + sizeof(uint32_t))
return -1; return 0;
*value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1)); *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1));
return 5; return 5;
} }
if (additional_information == kAdditionalInformation8Bytes) { if (additional_information == kAdditionalInformation8Bytes) {
// 64 bit uint: 1 initial byte + 8 bytes payload. // 64 bit uint: 1 initial byte + 8 bytes payload.
if (bytes.size() < 1 + sizeof(uint64_t)) if (bytes.size() < 1 + sizeof(uint64_t))
return -1; return 0;
*value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1)); *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1));
return 9; return 9;
} }
return -1; return 0;
} }
// Writes the start of a token with |type|. The |value| may indicate the size, // Writes the start of a token with |type|. The |value| may indicate the size,
...@@ -770,10 +769,10 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { ...@@ -770,10 +769,10 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
SetToken(CBORTokenTag::NULL_VALUE, 1); SetToken(CBORTokenTag::NULL_VALUE, 1);
return; return;
case kExpectedConversionToBase64Tag: { // BINARY case kExpectedConversionToBase64Tag: { // BINARY
const int8_t bytes_read = internals::ReadTokenStart( const size_t bytes_read = internals::ReadTokenStart(
bytes_.subspan(status_.pos + 1), &token_start_type_, bytes_.subspan(status_.pos + 1), &token_start_type_,
&token_start_internal_value_); &token_start_internal_value_);
if (bytes_read < 0 || token_start_type_ != MajorType::BYTE_STRING || if (!bytes_read || token_start_type_ != MajorType::BYTE_STRING ||
token_start_internal_value_ > kMaxValidLength) { token_start_internal_value_ > kMaxValidLength) {
SetError(Error::CBOR_INVALID_BINARY); SetError(Error::CBOR_INVALID_BINARY);
return; return;
...@@ -823,47 +822,47 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { ...@@ -823,47 +822,47 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
return; return;
} }
default: { default: {
const int8_t token_start_length = internals::ReadTokenStart( const size_t bytes_read = internals::ReadTokenStart(
bytes_.subspan(status_.pos), &token_start_type_, bytes_.subspan(status_.pos), &token_start_type_,
&token_start_internal_value_); &token_start_internal_value_);
const bool success = token_start_length >= 0;
switch (token_start_type_) { switch (token_start_type_) {
case MajorType::UNSIGNED: // INT32. case MajorType::UNSIGNED: // INT32.
// INT32 is a signed int32 (int32 makes sense for the // INT32 is a signed int32 (int32 makes sense for the
// inspector_protocol, it's not a CBOR limitation), so we check // inspector_protocol, it's not a CBOR limitation), so we check
// against the signed max, so that the allowable values are // against the signed max, so that the allowable values are
// 0, 1, 2, ... 2^31 - 1. // 0, 1, 2, ... 2^31 - 1.
if (!success || std::numeric_limits<int32_t>::max() < if (!bytes_read || std::numeric_limits<int32_t>::max() <
token_start_internal_value_) { token_start_internal_value_) {
SetError(Error::CBOR_INVALID_INT32); SetError(Error::CBOR_INVALID_INT32);
return; return;
} }
SetToken(CBORTokenTag::INT32, token_start_length); SetToken(CBORTokenTag::INT32, bytes_read);
return; return;
case MajorType::NEGATIVE: { // INT32. case MajorType::NEGATIVE: { // INT32.
// INT32 is a signed int32 (int32 makes sense for the // INT32 is a signed int32 (int32 makes sense for the
// inspector_protocol, it's not a CBOR limitation); in CBOR, the // inspector_protocol, it's not a CBOR limitation); in CBOR, the
// negative values for INT32 are represented as NEGATIVE, that is, -1 // negative values for INT32 are represented as NEGATIVE, that is, -1
// INT32 is represented as 1 << 5 | 0 (major type 1, additional info // INT32 is represented as 1 << 5 | 0 (major type 1, additional info
// value 0). The minimal allowed INT32 value in our protocol is // value 0).
// std::numeric_limits<int32_t>::min(). We check for it by directly // The represented allowed values range is -1 to -2^31.
// checking the payload against the maximal allowed signed (!) int32 // They are mapped into the encoded range of 0 to 2^31-1.
// value. // We check the the payload in token_start_internal_value_ against
if (!success || token_start_internal_value_ > // that range (2^31-1 is also known as
// std::numeric_limits<int32_t>::max()).
if (!bytes_read || token_start_internal_value_ >
std::numeric_limits<int32_t>::max()) { std::numeric_limits<int32_t>::max()) {
SetError(Error::CBOR_INVALID_INT32); SetError(Error::CBOR_INVALID_INT32);
return; return;
} }
SetToken(CBORTokenTag::INT32, token_start_length); SetToken(CBORTokenTag::INT32, bytes_read);
return; return;
} }
case MajorType::STRING: { // STRING8. case MajorType::STRING: { // STRING8.
if (!success || token_start_internal_value_ > kMaxValidLength) { if (!bytes_read || token_start_internal_value_ > kMaxValidLength) {
SetError(Error::CBOR_INVALID_STRING8); SetError(Error::CBOR_INVALID_STRING8);
return; return;
} }
uint64_t token_byte_length = uint64_t token_byte_length = token_start_internal_value_ + bytes_read;
token_start_internal_value_ + token_start_length;
if (token_byte_length > remaining_bytes) { if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_STRING8); SetError(Error::CBOR_INVALID_STRING8);
return; return;
...@@ -875,13 +874,12 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { ...@@ -875,13 +874,12 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
case MajorType::BYTE_STRING: { // STRING16. case MajorType::BYTE_STRING: { // STRING16.
// Length must be divisible by 2 since UTF16 is 2 bytes per // Length must be divisible by 2 since UTF16 is 2 bytes per
// character, hence the &1 check. // character, hence the &1 check.
if (!success || token_start_internal_value_ > kMaxValidLength || if (!bytes_read || token_start_internal_value_ > kMaxValidLength ||
token_start_internal_value_ & 1) { token_start_internal_value_ & 1) {
SetError(Error::CBOR_INVALID_STRING16); SetError(Error::CBOR_INVALID_STRING16);
return; return;
} }
uint64_t token_byte_length = uint64_t token_byte_length = token_start_internal_value_ + bytes_read;
token_start_internal_value_ + token_start_length;
if (token_byte_length > remaining_bytes) { if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_STRING16); SetError(Error::CBOR_INVALID_STRING16);
return; return;
......
...@@ -427,7 +427,7 @@ Status AppendString8EntryToCBORMap(span<uint8_t> string8_key, ...@@ -427,7 +427,7 @@ Status AppendString8EntryToCBORMap(span<uint8_t> string8_key,
std::string* cbor); std::string* cbor);
namespace internals { // Exposed only for writing tests. namespace internals { // Exposed only for writing tests.
int8_t ReadTokenStart(span<uint8_t> bytes, size_t ReadTokenStart(span<uint8_t> bytes,
cbor::MajorType* type, cbor::MajorType* type,
uint64_t* value); uint64_t* value);
......
...@@ -235,7 +235,9 @@ TEST(EncodeDecodeInt32Test, RoundtripsInt32Max) { ...@@ -235,7 +235,9 @@ TEST(EncodeDecodeInt32Test, RoundtripsInt32Max) {
} }
TEST(EncodeDecodeInt32Test, RoundtripsInt32Min) { TEST(EncodeDecodeInt32Test, RoundtripsInt32Min) {
// std::numeric_limits<int32_t> is encoded as a uint32 after the initial byte. // std::numeric_limits<int32_t> is encoded as a uint32 (4 unsigned bytes)
// after the initial byte, which effectively carries the sign by
// designating the token as NEGATIVE.
std::vector<uint8_t> encoded; std::vector<uint8_t> encoded;
EncodeInt32(std::numeric_limits<int32_t>::min(), &encoded); EncodeInt32(std::numeric_limits<int32_t>::min(), &encoded);
// 1 for initial byte, 4 for the uint32. // 1 for initial byte, 4 for the uint32.
...@@ -248,6 +250,10 @@ TEST(EncodeDecodeInt32Test, RoundtripsInt32Min) { ...@@ -248,6 +250,10 @@ TEST(EncodeDecodeInt32Test, RoundtripsInt32Min) {
CBORTokenizer tokenizer(SpanFrom(encoded)); CBORTokenizer tokenizer(SpanFrom(encoded));
EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
EXPECT_EQ(std::numeric_limits<int32_t>::min(), tokenizer.GetInt32()); EXPECT_EQ(std::numeric_limits<int32_t>::min(), tokenizer.GetInt32());
// It's nice to see how the min int32 value reads in hex:
// That is, -1 minus the unsigned payload (0x7fffffff, see above).
int32_t expected = -1 - 0x7fffffff;
EXPECT_EQ(expected, tokenizer.GetInt32());
tokenizer.Next(); tokenizer.Next();
EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
} }
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
//#include "Values.h" //#include "Values.h"
{% if config.encoding_lib.header %}
#include "{{config.encoding_lib.header}}"
{% endif %}
{% for namespace in config.protocol.namespace %} {% for namespace in config.protocol.namespace %}
namespace {{namespace}} { namespace {{namespace}} {
{% endfor %} {% endfor %}
...@@ -64,6 +68,30 @@ void escapeStringForJSONInternal(const Char* str, unsigned len, ...@@ -64,6 +68,30 @@ void escapeStringForJSONInternal(const Char* str, unsigned len,
// to this constant. // to this constant.
static constexpr int kStackLimitValues = 1000; static constexpr int kStackLimitValues = 1000;
{% if config.encoding_lib.namespace %}
using {{"::".join(config.encoding_lib.namespace)}}::Error;
using {{"::".join(config.encoding_lib.namespace)}}::Status;
using {{"::".join(config.encoding_lib.namespace)}}::span;
namespace cbor {
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::CBORTokenTag;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::CBORTokenizer;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeBinary;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeDouble;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeFalse;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeFromLatin1;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeFromUTF16;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeIndefiniteLengthArrayStart;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeIndefiniteLengthMapStart;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeInt32;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeNull;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeStop;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeString8;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EncodeTrue;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::EnvelopeEncoder;
using {{"::".join(config.encoding_lib.namespace + ['cbor'])}}::InitialByteForEnvelope;
} // namespace cbor
{% endif %}
// Below are three parsing routines for CBOR, which cover enough // Below are three parsing routines for CBOR, which cover enough
// to roundtrip JSON messages. // to roundtrip JSON messages.
std::unique_ptr<DictionaryValue> parseMap(int32_t stack_depth, cbor::CBORTokenizer* tokenizer); std::unique_ptr<DictionaryValue> parseMap(int32_t stack_depth, cbor::CBORTokenizer* tokenizer);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
{% if config.encoding_lib.header == "" %}
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
...@@ -192,11 +193,10 @@ namespace internals { ...@@ -192,11 +193,10 @@ namespace internals {
// |type| is the major type as specified in RFC 7049 Section 2.1. // |type| is the major type as specified in RFC 7049 Section 2.1.
// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size // |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
// (e.g. for BYTE_STRING). // (e.g. for BYTE_STRING).
// If successful, returns the number of bytes read. Otherwise returns -1. // If successful, returns the number of bytes read. Otherwise returns 0.
// TODO(johannes): change return type to size_t and use 0 for error. size_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
if (bytes.empty()) if (bytes.empty())
return -1; return 0;
uint8_t initial_byte = bytes[0]; uint8_t initial_byte = bytes[0];
*type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift); *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift);
...@@ -210,32 +210,32 @@ int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) { ...@@ -210,32 +210,32 @@ int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
if (additional_information == kAdditionalInformation1Byte) { if (additional_information == kAdditionalInformation1Byte) {
// Values 24-255 are encoded with one initial byte, followed by the value. // Values 24-255 are encoded with one initial byte, followed by the value.
if (bytes.size() < 2) if (bytes.size() < 2)
return -1; return 0;
*value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1)); *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1));
return 2; return 2;
} }
if (additional_information == kAdditionalInformation2Bytes) { if (additional_information == kAdditionalInformation2Bytes) {
// Values 256-65535: 1 initial byte + 2 bytes payload. // Values 256-65535: 1 initial byte + 2 bytes payload.
if (bytes.size() < 1 + sizeof(uint16_t)) if (bytes.size() < 1 + sizeof(uint16_t))
return -1; return 0;
*value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1)); *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1));
return 3; return 3;
} }
if (additional_information == kAdditionalInformation4Bytes) { if (additional_information == kAdditionalInformation4Bytes) {
// 32 bit uint: 1 initial byte + 4 bytes payload. // 32 bit uint: 1 initial byte + 4 bytes payload.
if (bytes.size() < 1 + sizeof(uint32_t)) if (bytes.size() < 1 + sizeof(uint32_t))
return -1; return 0;
*value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1)); *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1));
return 5; return 5;
} }
if (additional_information == kAdditionalInformation8Bytes) { if (additional_information == kAdditionalInformation8Bytes) {
// 64 bit uint: 1 initial byte + 8 bytes payload. // 64 bit uint: 1 initial byte + 8 bytes payload.
if (bytes.size() < 1 + sizeof(uint64_t)) if (bytes.size() < 1 + sizeof(uint64_t))
return -1; return 0;
*value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1)); *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1));
return 9; return 9;
} }
return -1; return 0;
} }
// Writes the start of a token with |type|. The |value| may indicate the size, // Writes the start of a token with |type|. The |value| may indicate the size,
...@@ -777,10 +777,10 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { ...@@ -777,10 +777,10 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
SetToken(CBORTokenTag::NULL_VALUE, 1); SetToken(CBORTokenTag::NULL_VALUE, 1);
return; return;
case kExpectedConversionToBase64Tag: { // BINARY case kExpectedConversionToBase64Tag: { // BINARY
const int8_t bytes_read = internals::ReadTokenStart( const size_t bytes_read = internals::ReadTokenStart(
bytes_.subspan(status_.pos + 1), &token_start_type_, bytes_.subspan(status_.pos + 1), &token_start_type_,
&token_start_internal_value_); &token_start_internal_value_);
if (bytes_read < 0 || token_start_type_ != MajorType::BYTE_STRING || if (!bytes_read || token_start_type_ != MajorType::BYTE_STRING ||
token_start_internal_value_ > kMaxValidLength) { token_start_internal_value_ > kMaxValidLength) {
SetError(Error::CBOR_INVALID_BINARY); SetError(Error::CBOR_INVALID_BINARY);
return; return;
...@@ -830,47 +830,47 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { ...@@ -830,47 +830,47 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
return; return;
} }
default: { default: {
const int8_t token_start_length = internals::ReadTokenStart( const size_t bytes_read = internals::ReadTokenStart(
bytes_.subspan(status_.pos), &token_start_type_, bytes_.subspan(status_.pos), &token_start_type_,
&token_start_internal_value_); &token_start_internal_value_);
const bool success = token_start_length >= 0;
switch (token_start_type_) { switch (token_start_type_) {
case MajorType::UNSIGNED: // INT32. case MajorType::UNSIGNED: // INT32.
// INT32 is a signed int32 (int32 makes sense for the // INT32 is a signed int32 (int32 makes sense for the
// inspector_protocol, it's not a CBOR limitation), so we check // inspector_protocol, it's not a CBOR limitation), so we check
// against the signed max, so that the allowable values are // against the signed max, so that the allowable values are
// 0, 1, 2, ... 2^31 - 1. // 0, 1, 2, ... 2^31 - 1.
if (!success || std::numeric_limits<int32_t>::max() < if (!bytes_read || std::numeric_limits<int32_t>::max() <
token_start_internal_value_) { token_start_internal_value_) {
SetError(Error::CBOR_INVALID_INT32); SetError(Error::CBOR_INVALID_INT32);
return; return;
} }
SetToken(CBORTokenTag::INT32, token_start_length); SetToken(CBORTokenTag::INT32, bytes_read);
return; return;
case MajorType::NEGATIVE: { // INT32. case MajorType::NEGATIVE: { // INT32.
// INT32 is a signed int32 (int32 makes sense for the // INT32 is a signed int32 (int32 makes sense for the
// inspector_protocol, it's not a CBOR limitation); in CBOR, the // inspector_protocol, it's not a CBOR limitation); in CBOR, the
// negative values for INT32 are represented as NEGATIVE, that is, -1 // negative values for INT32 are represented as NEGATIVE, that is, -1
// INT32 is represented as 1 << 5 | 0 (major type 1, additional info // INT32 is represented as 1 << 5 | 0 (major type 1, additional info
// value 0). The minimal allowed INT32 value in our protocol is // value 0).
// std::numeric_limits<int32_t>::min(). We check for it by directly // The represented allowed values range is -1 to -2^31.
// checking the payload against the maximal allowed signed (!) int32 // They are mapped into the encoded range of 0 to 2^31-1.
// value. // We check the the payload in token_start_internal_value_ against
if (!success || token_start_internal_value_ > // that range (2^31-1 is also known as
// std::numeric_limits<int32_t>::max()).
if (!bytes_read || token_start_internal_value_ >
std::numeric_limits<int32_t>::max()) { std::numeric_limits<int32_t>::max()) {
SetError(Error::CBOR_INVALID_INT32); SetError(Error::CBOR_INVALID_INT32);
return; return;
} }
SetToken(CBORTokenTag::INT32, token_start_length); SetToken(CBORTokenTag::INT32, bytes_read);
return; return;
} }
case MajorType::STRING: { // STRING8. case MajorType::STRING: { // STRING8.
if (!success || token_start_internal_value_ > kMaxValidLength) { if (!bytes_read || token_start_internal_value_ > kMaxValidLength) {
SetError(Error::CBOR_INVALID_STRING8); SetError(Error::CBOR_INVALID_STRING8);
return; return;
} }
uint64_t token_byte_length = uint64_t token_byte_length = token_start_internal_value_ + bytes_read;
token_start_internal_value_ + token_start_length;
if (token_byte_length > remaining_bytes) { if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_STRING8); SetError(Error::CBOR_INVALID_STRING8);
return; return;
...@@ -882,13 +882,12 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { ...@@ -882,13 +882,12 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
case MajorType::BYTE_STRING: { // STRING16. case MajorType::BYTE_STRING: { // STRING16.
// Length must be divisible by 2 since UTF16 is 2 bytes per // Length must be divisible by 2 since UTF16 is 2 bytes per
// character, hence the &1 check. // character, hence the &1 check.
if (!success || token_start_internal_value_ > kMaxValidLength || if (!bytes_read || token_start_internal_value_ > kMaxValidLength ||
token_start_internal_value_ & 1) { token_start_internal_value_ & 1) {
SetError(Error::CBOR_INVALID_STRING16); SetError(Error::CBOR_INVALID_STRING16);
return; return;
} }
uint64_t token_byte_length = uint64_t token_byte_length = token_start_internal_value_ + bytes_read;
token_start_internal_value_ + token_start_length;
if (token_byte_length > remaining_bytes) { if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_STRING16); SetError(Error::CBOR_INVALID_STRING16);
return; return;
...@@ -2199,3 +2198,4 @@ Status ConvertJSONToCBOR(const Platform& platform, ...@@ -2199,3 +2198,4 @@ Status ConvertJSONToCBOR(const Platform& platform,
} // namespace {{namespace}} } // namespace {{namespace}}
{% endfor %} {% endfor %}
{% endif %}
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
{% if config.encoding_lib.header == "" %}
#ifndef {{"_".join(config.protocol.namespace)}}_encoding_h #ifndef {{"_".join(config.protocol.namespace)}}_encoding_h
#define {{"_".join(config.protocol.namespace)}}_encoding_h #define {{"_".join(config.protocol.namespace)}}_encoding_h
...@@ -435,7 +436,7 @@ Status AppendString8EntryToCBORMap(span<uint8_t> string8_key, ...@@ -435,7 +436,7 @@ Status AppendString8EntryToCBORMap(span<uint8_t> string8_key,
std::string* cbor); std::string* cbor);
namespace internals { // Exposed only for writing tests. namespace internals { // Exposed only for writing tests.
int8_t ReadTokenStart(span<uint8_t> bytes, size_t ReadTokenStart(span<uint8_t> bytes,
cbor::MajorType* type, cbor::MajorType* type,
uint64_t* value); uint64_t* value);
...@@ -518,3 +519,4 @@ Status ConvertJSONToCBOR(const Platform& platform, ...@@ -518,3 +519,4 @@ Status ConvertJSONToCBOR(const Platform& platform,
} // namespace {{namespace}} } // namespace {{namespace}}
{% endfor %} {% endfor %}
#endif // !defined({{"_".join(config.protocol.namespace)}}_encoding_h) #endif // !defined({{"_".join(config.protocol.namespace)}}_encoding_h)
{% endif %}
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