Commit 99feae23 authored by Johannes Henkel's avatar Johannes Henkel Committed by Commit Bot

[DevTools] Roll inspector protocol for V8

New revision: 0aafd2876f7485db7b07c513c0457b7cbbbe3304

https://chromium.googlesource.com/deps/inspector_protocol/+/0aafd2876f7485db7b07c513c0457b7cbbbe3304

Change-Id: I6e9babc8401a5af3085cce81b963f288d0392c07
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1613478Reviewed-by: 's avatarAlexei Filippov <alph@chromium.org>
Commit-Queue: Johannes Henkel <johannes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61620}
parent 2ebff719
......@@ -2,7 +2,7 @@ Name: inspector protocol
Short Name: inspector_protocol
URL: https://chromium.googlesource.com/deps/inspector_protocol/
Version: 0
Revision: 50a14c3884caf012f3a5fc666d5eb8033d8a184a
Revision: 0aafd2876f7485db7b07c513c0457b7cbbbe3304
License: BSD
License File: LICENSE
Security Critical: no
......
......@@ -4,6 +4,7 @@
#include "encoding.h"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
......@@ -171,9 +172,9 @@ void WriteBytesMostSignificantByteFirst(T v, C* out) {
// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
template <typename T>
T ReadBytesMostSignificantByteFirst(span<uint8_t> in) {
assert(static_cast<std::size_t>(in.size()) >= sizeof(T));
assert(in.size() >= sizeof(T));
T result = 0;
for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes)
for (size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes)
result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8);
return result;
}
......@@ -185,6 +186,7 @@ namespace internals {
// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
// (e.g. for BYTE_STRING).
// If successful, returns the number of bytes read. Otherwise returns -1.
// TODO(johannes): change return type to size_t and use 0 for error.
int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
if (bytes.empty())
return -1;
......@@ -207,21 +209,21 @@ int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
}
if (additional_information == kAdditionalInformation2Bytes) {
// Values 256-65535: 1 initial byte + 2 bytes payload.
if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint16_t))
if (bytes.size() < 1 + sizeof(uint16_t))
return -1;
*value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1));
return 3;
}
if (additional_information == kAdditionalInformation4Bytes) {
// 32 bit uint: 1 initial byte + 4 bytes payload.
if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint32_t))
if (bytes.size() < 1 + sizeof(uint32_t))
return -1;
*value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1));
return 5;
}
if (additional_information == kAdditionalInformation8Bytes) {
// 64 bit uint: 1 initial byte + 8 bytes payload.
if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint64_t))
if (bytes.size() < 1 + sizeof(uint64_t))
return -1;
*value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1));
return 9;
......@@ -369,7 +371,7 @@ void EncodeString8(span<uint8_t> in, std::string* out) {
template <typename C>
void EncodeFromLatin1Tmpl(span<uint8_t> latin1, C* out) {
for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) {
for (size_t ii = 0; ii < latin1.size(); ++ii) {
if (latin1[ii] <= 127)
continue;
// If there's at least one non-ASCII char, convert to UTF8.
......@@ -432,12 +434,12 @@ void EncodeBinary(span<uint8_t> in, std::string* out) {
// A double is encoded with a specific initial byte
// (kInitialByteForDouble) plus the 64 bits of payload for its value.
constexpr std::ptrdiff_t kEncodedDoubleSize = 1 + sizeof(uint64_t);
constexpr size_t kEncodedDoubleSize = 1 + sizeof(uint64_t);
// An envelope is encoded with a specific initial byte
// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32
// bit wide length, plus a 32 bit length for that string.
constexpr std::ptrdiff_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t);
constexpr size_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t);
template <typename C>
void EncodeDoubleTmpl(double value, C* out) {
......@@ -463,7 +465,7 @@ void EncodeDouble(double value, std::string* out) {
// =============================================================================
template <typename C>
void EncodeStartTmpl(C* out, std::size_t* byte_size_pos) {
void EncodeStartTmpl(C* out, size_t* byte_size_pos) {
assert(*byte_size_pos == 0);
out->push_back(kInitialByteForEnvelope);
out->push_back(kInitialByteFor32BitLengthByteString);
......@@ -480,7 +482,7 @@ void EnvelopeEncoder::EncodeStart(std::string* out) {
}
template <typename C>
bool EncodeStopTmpl(C* out, std::size_t* byte_size_pos) {
bool EncodeStopTmpl(C* out, size_t* byte_size_pos) {
assert(*byte_size_pos != 0);
// The byte size is the size of the payload, that is, all the
// bytes that were written past the byte size position itself.
......@@ -657,10 +659,17 @@ Status CBORTokenizer::Status() const {
return status_;
}
// The following accessor functions ::GetInt32, ::GetDouble,
// ::GetString8, ::GetString16WireRep, ::GetBinary, ::GetEnvelopeContents
// assume that a particular token was recognized in ::ReadNextToken.
// That's where all the error checking is done. By design,
// the accessors (assuming the token was recognized) never produce
// an error.
int32_t CBORTokenizer::GetInt32() const {
assert(token_tag_ == CBORTokenTag::INT32);
// The range checks happen in ::ReadNextToken().
return static_cast<uint32_t>(
return static_cast<int32_t>(
token_start_type_ == MajorType::UNSIGNED
? token_start_internal_value_
: -static_cast<int64_t>(token_start_internal_value_) - 1);
......@@ -679,28 +688,55 @@ double CBORTokenizer::GetDouble() const {
span<uint8_t> CBORTokenizer::GetString8() const {
assert(token_tag_ == CBORTokenTag::STRING8);
auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
auto length = static_cast<size_t>(token_start_internal_value_);
return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
}
span<uint8_t> CBORTokenizer::GetString16WireRep() const {
assert(token_tag_ == CBORTokenTag::STRING16);
auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
auto length = static_cast<size_t>(token_start_internal_value_);
return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
}
span<uint8_t> CBORTokenizer::GetBinary() const {
assert(token_tag_ == CBORTokenTag::BINARY);
auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
auto length = static_cast<size_t>(token_start_internal_value_);
return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
}
span<uint8_t> CBORTokenizer::GetEnvelopeContents() const {
assert(token_tag_ == CBORTokenTag::ENVELOPE);
auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
auto length = static_cast<size_t>(token_start_internal_value_);
return bytes_.subspan(status_.pos + kEncodedEnvelopeHeaderSize, length);
}
// All error checking happens in ::ReadNextToken, so that the accessors
// can avoid having to carry an error return value.
//
// With respect to checking the encoded lengths of strings, arrays, etc:
// On the wire, CBOR uses 1,2,4, and 8 byte unsigned integers, so
// we initially read them as uint64_t, usually into token_start_internal_value_.
//
// However, since these containers have a representation on the machine,
// we need to do corresponding size computations on the input byte array,
// output span (e.g. the payload for a string), etc., and size_t is
// machine specific (in practice either 32 bit or 64 bit).
//
// Further, we must avoid overflowing size_t. Therefore, we use this
// kMaxValidLength constant to:
// - Reject values that are larger than the architecture specific
// max size_t (differs between 32 bit and 64 bit arch).
// - Reserve at least one bit so that we can check against overflows
// when adding lengths (array / string length / etc.); we do this by
// ensuring that the inputs to an addition are <= kMaxValidLength,
// and then checking whether the sum went past it.
//
// See also
// https://chromium.googlesource.com/chromium/src/+/master/docs/security/integer-semantics.md
static const uint64_t kMaxValidLength =
std::min<uint64_t>(std::numeric_limits<uint64_t>::max() >> 2,
std::numeric_limits<size_t>::max());
void CBORTokenizer::ReadNextToken(bool enter_envelope) {
if (enter_envelope) {
status_.pos += kEncodedEnvelopeHeaderSize;
......@@ -713,6 +749,7 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
token_tag_ = CBORTokenTag::DONE;
return;
}
const size_t remaining_bytes = bytes_.size() - status_.pos;
switch (bytes_[status_.pos]) {
case kStopByte:
SetToken(CBORTokenTag::STOP, 1);
......@@ -733,21 +770,26 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
SetToken(CBORTokenTag::NULL_VALUE, 1);
return;
case kExpectedConversionToBase64Tag: { // BINARY
int8_t bytes_read = internals::ReadTokenStart(
const int8_t bytes_read = internals::ReadTokenStart(
bytes_.subspan(status_.pos + 1), &token_start_type_,
&token_start_internal_value_);
int64_t token_byte_length = 1 + bytes_read + token_start_internal_value_;
if (-1 == bytes_read || token_start_type_ != MajorType::BYTE_STRING ||
status_.pos + token_byte_length > bytes_.size()) {
if (bytes_read < 0 || token_start_type_ != MajorType::BYTE_STRING ||
token_start_internal_value_ > kMaxValidLength) {
SetError(Error::CBOR_INVALID_BINARY);
return;
}
SetToken(CBORTokenTag::BINARY,
static_cast<std::ptrdiff_t>(token_byte_length));
const uint64_t token_byte_length = token_start_internal_value_ +
/* tag before token start: */ 1 +
/* token start: */ bytes_read;
if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_BINARY);
return;
}
SetToken(CBORTokenTag::BINARY, static_cast<size_t>(token_byte_length));
return;
}
case kInitialByteForDouble: { // DOUBLE
if (status_.pos + kEncodedDoubleSize > bytes_.size()) {
if (kEncodedDoubleSize > remaining_bytes) {
SetError(Error::CBOR_INVALID_DOUBLE);
return;
}
......@@ -755,7 +797,7 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
return;
}
case kInitialByteForEnvelope: { // ENVELOPE
if (status_.pos + kEncodedEnvelopeHeaderSize > bytes_.size()) {
if (kEncodedEnvelopeHeaderSize > remaining_bytes) {
SetError(Error::CBOR_INVALID_ENVELOPE);
return;
}
......@@ -767,26 +809,30 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
// Read the length of the byte string.
token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>(
bytes_.subspan(status_.pos + 2));
// Make sure the payload is contained within the message.
if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize +
status_.pos >
static_cast<std::size_t>(bytes_.size())) {
if (token_start_internal_value_ > kMaxValidLength) {
SetError(Error::CBOR_INVALID_ENVELOPE);
return;
}
auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
SetToken(CBORTokenTag::ENVELOPE, kEncodedEnvelopeHeaderSize + length);
uint64_t token_byte_length =
token_start_internal_value_ + kEncodedEnvelopeHeaderSize;
if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_ENVELOPE);
return;
}
SetToken(CBORTokenTag::ENVELOPE, static_cast<size_t>(token_byte_length));
return;
}
default: {
span<uint8_t> remainder =
bytes_.subspan(status_.pos, bytes_.size() - status_.pos);
assert(!remainder.empty());
int8_t token_start_length = internals::ReadTokenStart(
remainder, &token_start_type_, &token_start_internal_value_);
bool success = token_start_length != -1;
const int8_t token_start_length = internals::ReadTokenStart(
bytes_.subspan(status_.pos), &token_start_type_,
&token_start_internal_value_);
const bool success = token_start_length >= 0;
switch (token_start_type_) {
case MajorType::UNSIGNED: // INT32.
// INT32 is a signed int32 (int32 makes sense for the
// inspector_protocol, it's not a CBOR limitation), so we check
// against the signed max, so that the allowable values are
// 0, 1, 2, ... 2^31 - 1.
if (!success || std::numeric_limits<int32_t>::max() <
token_start_internal_value_) {
SetError(Error::CBOR_INVALID_INT32);
......@@ -794,46 +840,53 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
}
SetToken(CBORTokenTag::INT32, token_start_length);
return;
case MajorType::NEGATIVE: // INT32.
if (!success ||
std::numeric_limits<int32_t>::min() >
-static_cast<int64_t>(token_start_internal_value_) - 1) {
case MajorType::NEGATIVE: { // INT32.
// INT32 is a signed int32 (int32 makes sense for the
// inspector_protocol, it's not a CBOR limitation); in CBOR,
// the negative values for INT32 are represented as NEGATIVE,
// that is, -1 INT32 is represented as 1 << 5 | 0 (major type 1,
// additional info value 0). So here, we compute the INT32 value
// and then check it against the INT32 min.
int64_t actual_value =
-static_cast<int64_t>(token_start_internal_value_) - 1;
if (!success || actual_value < std::numeric_limits<int32_t>::min()) {
SetError(Error::CBOR_INVALID_INT32);
return;
}
SetToken(CBORTokenTag::INT32, token_start_length);
return;
}
case MajorType::STRING: { // STRING8.
if (!success) {
if (!success || token_start_internal_value_ > kMaxValidLength) {
SetError(Error::CBOR_INVALID_STRING8);
return;
}
auto length =
static_cast<std::ptrdiff_t>(token_start_internal_value_);
if (remainder.size() < token_start_length + length) {
uint64_t token_byte_length =
token_start_internal_value_ + token_start_length;
if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_STRING8);
return;
}
SetToken(CBORTokenTag::STRING8, token_start_length + length);
SetToken(CBORTokenTag::STRING8,
static_cast<size_t>(token_byte_length));
return;
}
case MajorType::BYTE_STRING: { // STRING16.
if (!success) {
SetError(Error::CBOR_INVALID_STRING16);
return;
}
auto length =
static_cast<std::ptrdiff_t>(token_start_internal_value_);
if (remainder.size() < token_start_length + length) {
// Length must be divisible by 2 since UTF16 is 2 bytes per
// character, hence the &1 check.
if (!success || token_start_internal_value_ > kMaxValidLength ||
token_start_internal_value_ & 1) {
SetError(Error::CBOR_INVALID_STRING16);
return;
}
if (length & 1) {
// Must be divisible by 2 since UTF16 is 2 bytes per character.
uint64_t token_byte_length =
token_start_internal_value_ + token_start_length;
if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_STRING16);
return;
}
SetToken(CBORTokenTag::STRING16, token_start_length + length);
SetToken(CBORTokenTag::STRING16,
static_cast<size_t>(token_byte_length));
return;
}
case MajorType::ARRAY:
......@@ -847,8 +900,7 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
}
}
void CBORTokenizer::SetToken(CBORTokenTag token_tag,
std::ptrdiff_t token_byte_length) {
void CBORTokenizer::SetToken(CBORTokenTag token_tag, size_t token_byte_length) {
token_tag_ = token_tag;
token_byte_length_ = token_byte_length;
}
......@@ -882,7 +934,7 @@ bool ParseValue(int32_t stack_depth,
void ParseUTF16String(CBORTokenizer* tokenizer, StreamingParserHandler* out) {
std::vector<uint16_t> value;
span<uint8_t> rep = tokenizer->GetString16WireRep();
for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2)
for (size_t ii = 0; ii < rep.size(); ii += 2)
value.push_back((rep[ii + 1] << 8) | rep[ii]);
out->HandleString16(span<uint16_t>(value.data(), value.size()));
tokenizer->Next();
......@@ -1074,9 +1126,9 @@ Status AppendString8EntryToCBORMapTmpl(span<uint8_t> string8_key,
return tokenizer.Status();
if (tokenizer.TokenTag() != CBORTokenTag::ENVELOPE)
return Status(Error::CBOR_INVALID_ENVELOPE, 0);
std::ptrdiff_t envelope_size = tokenizer.GetEnvelopeContents().size();
std::size_t old_size = cbor->size();
if (old_size != std::size_t(envelope_size) + kEncodedEnvelopeHeaderSize)
size_t envelope_size = tokenizer.GetEnvelopeContents().size();
size_t old_size = cbor->size();
if (old_size != envelope_size + kEncodedEnvelopeHeaderSize)
return Status(Error::CBOR_INVALID_ENVELOPE, 0);
if (envelope_size == 0 ||
(tokenizer.GetEnvelopeContents()[0] != EncodeIndefiniteLengthMapStart()))
......@@ -1087,10 +1139,10 @@ Status AppendString8EntryToCBORMapTmpl(span<uint8_t> string8_key,
EncodeString8(string8_key, cbor);
EncodeString8(string8_value, cbor);
cbor->push_back(EncodeStop());
std::size_t new_envelope_size = envelope_size + (cbor->size() - old_size);
size_t new_envelope_size = envelope_size + (cbor->size() - old_size);
if (new_envelope_size > std::numeric_limits<uint32_t>::max())
return Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, 0);
std::size_t size_pos = cbor->size() - new_envelope_size - sizeof(uint32_t);
size_t size_pos = cbor->size() - new_envelope_size - sizeof(uint32_t);
uint8_t* out = reinterpret_cast<uint8_t*>(&cbor->at(size_pos));
*(out++) = (new_envelope_size >> 24) & 0xff;
*(out++) = (new_envelope_size >> 16) & 0xff;
......@@ -1168,7 +1220,7 @@ void Base64Encode(const span<uint8_t>& in, C* out) {
// The following three cases are based on the tables in the example
// section in https://en.wikipedia.org/wiki/Base64. We process three
// input bytes at a time, emitting 4 output bytes at a time.
std::ptrdiff_t ii = 0;
size_t ii = 0;
// While possible, process three input bytes.
for (; ii + 3 <= in.size(); ii += 3) {
......@@ -1273,7 +1325,7 @@ class JSONEncoder : public StreamingParserHandler {
return;
state_.top().StartElement(out_);
Emit('"');
for (std::ptrdiff_t ii = 0; ii < chars.size(); ++ii) {
for (size_t ii = 0; ii < chars.size(); ++ii) {
uint8_t c = chars[ii];
if (c == '"') {
Emit("\\\"");
......@@ -1485,7 +1537,7 @@ class JsonParser {
JsonParser(const Platform* platform, StreamingParserHandler* handler)
: platform_(platform), handler_(handler) {}
void Parse(const Char* start, std::size_t length) {
void Parse(const Char* start, size_t length) {
start_pos_ = start;
const Char* end = start + length;
const Char* tokenEnd = nullptr;
......@@ -1498,12 +1550,10 @@ class JsonParser {
}
private:
bool CharsToDouble(const uint16_t* chars,
std::size_t length,
double* result) {
bool CharsToDouble(const uint16_t* chars, size_t length, double* result) {
std::string buffer;
buffer.reserve(length + 1);
for (std::size_t ii = 0; ii < length; ++ii) {
for (size_t ii = 0; ii < length; ++ii) {
bool is_ascii = !(chars[ii] & ~0x7F);
if (!is_ascii)
return false;
......@@ -1512,7 +1562,7 @@ class JsonParser {
return platform_->StrToD(buffer.c_str(), result);
}
bool CharsToDouble(const uint8_t* chars, std::size_t length, double* result) {
bool CharsToDouble(const uint8_t* chars, size_t length, double* result) {
std::string buffer(reinterpret_cast<const char*>(chars), length);
return platform_->StrToD(buffer.c_str(), result);
}
......@@ -2055,7 +2105,8 @@ class JsonParser {
void HandleError(Error error, const Char* pos) {
assert(error != Error::OK);
if (!error_) {
handler_->HandleError(Status{error, pos - start_pos_});
handler_->HandleError(
Status{error, static_cast<size_t>(pos - start_pos_)});
error_ = true;
}
}
......
......@@ -8,6 +8,7 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <limits>
#include <memory>
#include <string>
#include <vector>
......@@ -18,13 +19,11 @@ namespace v8_inspector_protocol_encoding {
// span - sequence of bytes
// =============================================================================
// This template is similar to std::span, which will be included in C++20. Like
// std::span it uses ptrdiff_t, which is signed (and thus a bit annoying
// sometimes when comparing with size_t), but other than this it's much simpler.
// This template is similar to std::span, which will be included in C++20.
template <typename T>
class span {
public:
using index_type = std::ptrdiff_t;
using index_type = size_t;
span() : data_(nullptr), size_(0) {}
span(const T* data, index_type size) : data_(data), size_(size) {}
......@@ -116,13 +115,13 @@ enum class Error {
// A status value with position that can be copied. The default status
// is OK. Usually, error status values should come with a valid position.
struct Status {
static constexpr std::ptrdiff_t npos() { return -1; }
static constexpr size_t npos() { return std::numeric_limits<size_t>::max(); }
bool ok() const { return error == Error::OK; }
Error error = Error::OK;
std::ptrdiff_t pos = npos();
Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {}
size_t pos = npos();
Status(Error error, size_t pos) : error(error), pos(pos) {}
Status() = default;
// Returns a 7 bit US-ASCII string, either "OK" or an error message
......@@ -268,7 +267,7 @@ class EnvelopeEncoder {
bool EncodeStop(std::string* out);
private:
std::size_t byte_size_pos_ = 0;
size_t byte_size_pos_ = 0;
};
// =============================================================================
......@@ -392,13 +391,13 @@ class CBORTokenizer {
private:
void ReadNextToken(bool enter_envelope);
void SetToken(CBORTokenTag token, std::ptrdiff_t token_byte_length);
void SetToken(CBORTokenTag token, size_t token_byte_length);
void SetError(Error error);
span<uint8_t> bytes_;
CBORTokenTag token_tag_;
struct Status status_;
std::ptrdiff_t token_byte_length_;
size_t token_byte_length_;
MajorType token_start_type_;
uint64_t token_start_internal_value_;
};
......
......@@ -67,8 +67,8 @@ TYPED_TEST_SUITE(SpanTest, TestTypes);
TYPED_TEST(SpanTest, Empty) {
span<TypeParam> empty;
EXPECT_TRUE(empty.empty());
EXPECT_EQ(0, empty.size());
EXPECT_EQ(0, empty.size_bytes());
EXPECT_EQ(0u, empty.size());
EXPECT_EQ(0u, empty.size_bytes());
EXPECT_EQ(empty.begin(), empty.end());
}
......@@ -76,8 +76,8 @@ TYPED_TEST(SpanTest, SingleItem) {
TypeParam single_item = 42;
span<TypeParam> singular(&single_item, 1);
EXPECT_FALSE(singular.empty());
EXPECT_EQ(1, singular.size());
EXPECT_EQ(sizeof(TypeParam), static_cast<size_t>(singular.size_bytes()));
EXPECT_EQ(1u, singular.size());
EXPECT_EQ(sizeof(TypeParam), singular.size_bytes());
EXPECT_EQ(singular.begin() + 1, singular.end());
EXPECT_EQ(42, singular[0]);
}
......@@ -86,9 +86,8 @@ TYPED_TEST(SpanTest, FiveItems) {
std::vector<TypeParam> test_input = {31, 32, 33, 34, 35};
span<TypeParam> five_items(test_input.data(), 5);
EXPECT_FALSE(five_items.empty());
EXPECT_EQ(5, five_items.size());
EXPECT_EQ(sizeof(TypeParam) * 5,
static_cast<size_t>(five_items.size_bytes()));
EXPECT_EQ(5u, five_items.size());
EXPECT_EQ(sizeof(TypeParam) * 5, five_items.size_bytes());
EXPECT_EQ(five_items.begin() + 5, five_items.end());
EXPECT_EQ(31, five_items[0]);
EXPECT_EQ(32, five_items[1]);
......@@ -96,12 +95,12 @@ TYPED_TEST(SpanTest, FiveItems) {
EXPECT_EQ(34, five_items[3]);
EXPECT_EQ(35, five_items[4]);
span<TypeParam> three_items = five_items.subspan(2);
EXPECT_EQ(3, three_items.size());
EXPECT_EQ(3u, three_items.size());
EXPECT_EQ(33, three_items[0]);
EXPECT_EQ(34, three_items[1]);
EXPECT_EQ(35, three_items[2]);
span<TypeParam> two_items = five_items.subspan(2, 2);
EXPECT_EQ(2, two_items.size());
EXPECT_EQ(2u, two_items.size());
EXPECT_EQ(33, two_items[0]);
EXPECT_EQ(34, two_items[1]);
}
......@@ -109,17 +108,17 @@ TYPED_TEST(SpanTest, FiveItems) {
TEST(SpanFromTest, FromConstCharAndLiteral) {
// Testing this is useful because strlen(nullptr) is undefined.
EXPECT_EQ(nullptr, SpanFrom(nullptr).data());
EXPECT_EQ(0, SpanFrom(nullptr).size());
EXPECT_EQ(0u, SpanFrom(nullptr).size());
const char* kEmpty = "";
EXPECT_EQ(kEmpty, reinterpret_cast<const char*>(SpanFrom(kEmpty).data()));
EXPECT_EQ(0, SpanFrom(kEmpty).size());
EXPECT_EQ(0u, SpanFrom(kEmpty).size());
const char* kFoo = "foo";
EXPECT_EQ(kFoo, reinterpret_cast<const char*>(SpanFrom(kFoo).data()));
EXPECT_EQ(3, SpanFrom(kFoo).size());
EXPECT_EQ(3u, SpanFrom(kFoo).size());
EXPECT_EQ(3, SpanFrom("foo").size());
EXPECT_EQ(3u, SpanFrom("foo").size());
}
// =============================================================================
......@@ -201,7 +200,7 @@ TEST(EncodeDecodeInt32Test, RoundtripsUint16) {
std::vector<uint8_t> encoded;
EncodeInt32(500, &encoded);
// 1 for initial byte, 2 for uint16.
EXPECT_EQ(static_cast<std::size_t>(3), encoded.size());
EXPECT_EQ(3u, encoded.size());
// first three bits: major type = 0;
// remaining five bits: additional info = 25, indicating payload is uint16.
EXPECT_EQ(25, encoded[0]);
......@@ -330,7 +329,7 @@ TEST(EncodeDecodeString16Test, RoundtripsEmpty) {
// CBORTokenizer.
std::vector<uint8_t> encoded;
EncodeString16(span<uint16_t>(), &encoded);
EXPECT_EQ(static_cast<std::size_t>(1), encoded.size());
EXPECT_EQ(1u, encoded.size());
// first three bits: major type = 2; remaining five bits: additional info =
// size 0.
EXPECT_EQ(2 << 5, encoded[0]);
......@@ -349,9 +348,10 @@ TEST(EncodeDecodeString16Test, RoundtripsEmpty) {
// so this routine follows the advice in
// https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html.
std::vector<uint16_t> String16WireRepToHost(span<uint8_t> in) {
CHECK_EQ(in.size() & 1, 0); // must be even number of bytes.
// must be even number of bytes.
CHECK_EQ(in.size() & 1, 0u);
std::vector<uint16_t> host_out;
for (std::ptrdiff_t ii = 0; ii < in.size(); ii += 2)
for (size_t ii = 0; ii < in.size(); ii += 2)
host_out.push_back(in[ii + 1] << 8 | in[ii]);
return host_out;
}
......@@ -399,7 +399,7 @@ TEST(EncodeDecodeString16Test, Roundtrips500) {
two_fifty.push_back(ii);
std::vector<uint8_t> encoded;
EncodeString16(span<uint16_t>(two_fifty.data(), two_fifty.size()), &encoded);
EXPECT_EQ(static_cast<std::size_t>(3 + 250 * 2), encoded.size());
EXPECT_EQ(3u + 250u * 2, encoded.size());
// Now check the first three bytes:
// Major type: 2 (BYTE_STRING)
// Additional information: 25, indicating size is represented by 2 bytes.
......@@ -428,7 +428,10 @@ TEST(EncodeDecodeString16Test, ErrorCases) {
"length must be divisible by 2 (but it's 1)"},
TestCase{{2 << 5 | 29}, "additional info = 29 isn't recognized"},
TestCase{{2 << 5 | 9, 1, 2, 3, 4, 5, 6, 7, 8},
"length (9) points just past the end of the test case"}}};
"length (9) points just past the end of the test case"},
TestCase{{2 << 5 | 27, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
'a', 'b', 'c'},
"large length pointing past the end of the test case"}}};
for (const TestCase& test : tests) {
SCOPED_TRACE(test.msg);
CBORTokenizer tokenizer(SpanFrom(test.data));
......@@ -474,7 +477,10 @@ TEST(EncodeDecodeString8Test, ErrorCases) {
std::vector<TestCase> tests{
{TestCase{{3 << 5 | 29}, "additional info = 29 isn't recognized"},
TestCase{{3 << 5 | 9, 1, 2, 3, 4, 5, 6, 7, 8},
"length (9) points just past the end of the test case"}}};
"length (9) points just past the end of the test case"},
TestCase{{3 << 5 | 27, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
'a', 'b', 'c'},
"large length pointing past the end of the test case"}}};
for (const TestCase& test : tests) {
SCOPED_TRACE(test.msg);
CBORTokenizer tokenizer(SpanFrom(test.data));
......@@ -562,6 +568,24 @@ TEST(EncodeDecodeBinaryTest, RoundtripsHelloWorld) {
EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
}
TEST(EncodeDecodeBinaryTest, ErrorCases) {
struct TestCase {
std::vector<uint8_t> data;
std::string msg;
};
std::vector<TestCase> tests{{TestCase{
{6 << 5 | 22, // tag 22 indicating base64 interpretation in JSON
2 << 5 | 27, // BYTE_STRING (type 2), followed by 8 bytes length
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
"large length pointing past the end of the test case"}}};
for (const TestCase& test : tests) {
SCOPED_TRACE(test.msg);
CBORTokenizer tokenizer(SpanFrom(test.data));
EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
EXPECT_EQ(Error::CBOR_INVALID_BINARY, tokenizer.Status().error);
}
}
//
// EncodeDouble / CBORTokenTag::DOUBLE
//
......@@ -866,7 +890,7 @@ TEST(ParseCBORTest, UnexpectedEofExpectedValueError) {
NewJSONEncoder(&GetTestPlatform(), &out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, status.error);
EXPECT_EQ(static_cast<int64_t>(bytes.size()), status.pos);
EXPECT_EQ(bytes.size(), status.pos);
EXPECT_EQ("", out);
}
......@@ -884,7 +908,7 @@ TEST(ParseCBORTest, UnexpectedEofInArrayError) {
NewJSONEncoder(&GetTestPlatform(), &out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, status.error);
EXPECT_EQ(static_cast<int64_t>(bytes.size()), status.pos);
EXPECT_EQ(bytes.size(), status.pos);
EXPECT_EQ("", out);
}
......@@ -899,7 +923,7 @@ TEST(ParseCBORTest, UnexpectedEofInMapError) {
NewJSONEncoder(&GetTestPlatform(), &out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_MAP, status.error);
EXPECT_EQ(7, status.pos);
EXPECT_EQ(7u, status.pos);
EXPECT_EQ("", out);
}
......@@ -916,7 +940,7 @@ TEST(ParseCBORTest, InvalidMapKeyError) {
NewJSONEncoder(&GetTestPlatform(), &out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_INVALID_MAP_KEY, status.error);
EXPECT_EQ(7, status.pos);
EXPECT_EQ(7u, status.pos);
EXPECT_EQ("", out);
}
......@@ -965,8 +989,8 @@ TEST(ParseCBORTest, StackLimitExceededError) {
// where the error is encountered. So we look at a small example and find
// the second envelope start.
std::vector<uint8_t> small_example = MakeNestedCBOR(3);
int64_t opening_segment_size = 1; // Start after the first envelope start.
while (opening_segment_size < static_cast<int64_t>(small_example.size()) &&
size_t opening_segment_size = 1; // Start after the first envelope start.
while (opening_segment_size < small_example.size() &&
small_example[opening_segment_size] != 0xd8)
opening_segment_size++;
......@@ -997,7 +1021,7 @@ TEST(ParseCBORTest, UnsupportedValueError) {
std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
0xbf}; // map start
EncodeString8(SpanFrom("key"), &bytes);
int64_t error_pos = bytes.size();
size_t error_pos = bytes.size();
bytes.push_back(6 << 5 | 5); // tags aren't supported yet.
EXPECT_EQ(kPayloadLen, bytes.size() - 6);
......@@ -1016,7 +1040,7 @@ TEST(ParseCBORTest, InvalidString16Error) {
std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
0xbf}; // map start
EncodeString8(SpanFrom("key"), &bytes);
int64_t error_pos = bytes.size();
size_t error_pos = bytes.size();
// a BYTE_STRING of length 5 as value; since we interpret these as string16,
// it's going to be invalid as each character would need two bytes, but
// 5 isn't divisible by 2.
......@@ -1039,7 +1063,7 @@ TEST(ParseCBORTest, InvalidString8Error) {
std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
0xbf}; // map start
EncodeString8(SpanFrom("key"), &bytes);
int64_t error_pos = bytes.size();
size_t error_pos = bytes.size();
// a STRING of length 5 as value, but we're at the end of the bytes array
// so it can't be decoded successfully.
bytes.push_back(3 << 5 | 5);
......@@ -1059,7 +1083,7 @@ TEST(ParseCBORTest, InvalidBinaryError) {
std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
0xbf}; // map start
EncodeString8(SpanFrom("key"), &bytes);
int64_t error_pos = bytes.size();
size_t error_pos = bytes.size();
bytes.push_back(6 << 5 | 22); // base64 hint for JSON; indicates binary
bytes.push_back(2 << 5 | 10); // BYTE_STRING (major type 2) of length 10
// Just two garbage bytes, not enough for the binary.
......@@ -1081,7 +1105,7 @@ TEST(ParseCBORTest, InvalidDoubleError) {
std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
0xbf}; // map start
EncodeString8(SpanFrom("key"), &bytes);
int64_t error_pos = bytes.size();
size_t error_pos = bytes.size();
bytes.push_back(7 << 5 | 27); // initial byte for double
// Just two garbage bytes, not enough to represent an actual double.
bytes.push_back(0x31);
......@@ -1102,7 +1126,7 @@ TEST(ParseCBORTest, InvalidSignedError) {
std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
0xbf}; // map start
EncodeString8(SpanFrom("key"), &bytes);
int64_t error_pos = bytes.size();
size_t error_pos = bytes.size();
// uint64_t max is a perfectly fine value to encode as CBOR unsigned,
// but we don't support this since we only cover the int32_t range.
internals::WriteTokenStart(MajorType::UNSIGNED,
......@@ -1125,7 +1149,7 @@ TEST(ParseCBORTest, TrailingJunk) {
EncodeString8(SpanFrom("key"), &bytes);
EncodeString8(SpanFrom("value"), &bytes);
bytes.push_back(0xff); // Up to here, it's a perfectly fine msg.
int64_t error_pos = bytes.size();
size_t error_pos = bytes.size();
EncodeString8(SpanFrom("trailing junk"), &bytes);
internals::WriteTokenStart(MajorType::UNSIGNED,
......@@ -1166,14 +1190,14 @@ TYPED_TEST(AppendString8EntryToMapTest, AppendsEntrySuccessfully) {
Status status =
AppendString8EntryToCBORMap(SpanFrom("foo"), SpanFrom("bar"), &msg);
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(-1, status.pos);
EXPECT_EQ(Status::npos(), status.pos);
std::string out;
std::unique_ptr<StreamingParserHandler> json_writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
ParseCBOR(SpanFrom(msg), json_writer.get());
EXPECT_EQ("{\"key\":\"value\",\"foo\":\"bar\"}", out);
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(-1, status.pos);
EXPECT_EQ(Status::npos(), status.pos);
}
TYPED_TEST(AppendString8EntryToMapTest, AppendThreeEntries) {
......@@ -1196,7 +1220,7 @@ TYPED_TEST(AppendString8EntryToMapTest, AppendThreeEntries) {
ParseCBOR(SpanFrom(msg), json_writer.get());
EXPECT_EQ("{\"key\":\"value\",\"key1\":\"value1\",\"key2\":\"value2\"}", out);
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(-1, status.pos);
EXPECT_EQ(Status::npos(), status.pos);
}
TYPED_TEST(AppendString8EntryToMapTest, MapStartExpected_Error) {
......@@ -1206,7 +1230,7 @@ TYPED_TEST(AppendString8EntryToMapTest, MapStartExpected_Error) {
Status status =
AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
EXPECT_EQ(Error::CBOR_MAP_START_EXPECTED, status.error);
EXPECT_EQ(6, status.pos);
EXPECT_EQ(6u, status.pos);
}
TYPED_TEST(AppendString8EntryToMapTest, MapStopExpected_Error) {
......@@ -1216,7 +1240,7 @@ TYPED_TEST(AppendString8EntryToMapTest, MapStopExpected_Error) {
Status status =
AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
EXPECT_EQ(Error::CBOR_MAP_STOP_EXPECTED, status.error);
EXPECT_EQ(7, status.pos);
EXPECT_EQ(7u, status.pos);
}
TYPED_TEST(AppendString8EntryToMapTest, InvalidEnvelope_Error) {
......@@ -1227,7 +1251,7 @@ TYPED_TEST(AppendString8EntryToMapTest, InvalidEnvelope_Error) {
Status status =
AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
EXPECT_EQ(Error::CBOR_INVALID_ENVELOPE, status.error);
EXPECT_EQ(0, status.pos);
EXPECT_EQ(0u, status.pos);
}
{ // Second byte is wrong.
std::vector<uint8_t> bytes = {
......@@ -1236,7 +1260,7 @@ TYPED_TEST(AppendString8EntryToMapTest, InvalidEnvelope_Error) {
Status status =
AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
EXPECT_EQ(Error::CBOR_INVALID_ENVELOPE, status.error);
EXPECT_EQ(0, status.pos);
EXPECT_EQ(0u, status.pos);
}
{ // Invalid envelope size example.
std::vector<uint8_t> bytes = {
......@@ -1246,7 +1270,7 @@ TYPED_TEST(AppendString8EntryToMapTest, InvalidEnvelope_Error) {
Status status =
AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
EXPECT_EQ(Error::CBOR_INVALID_ENVELOPE, status.error);
EXPECT_EQ(0, status.pos);
EXPECT_EQ(0u, status.pos);
}
{ // Invalid envelope size example.
std::vector<uint8_t> bytes = {
......@@ -1256,7 +1280,7 @@ TYPED_TEST(AppendString8EntryToMapTest, InvalidEnvelope_Error) {
Status status =
AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
EXPECT_EQ(Error::CBOR_INVALID_ENVELOPE, status.error);
EXPECT_EQ(0, status.pos);
EXPECT_EQ(0u, status.pos);
}
}
} // namespace cbor
......@@ -1386,7 +1410,7 @@ TEST(JsonStdStringWriterTest, HandlesErrors) {
WriteUTF8AsUTF16(writer.get(), "msg1");
writer->HandleError(Status{Error::JSON_PARSER_VALUE_EXPECTED, 42});
EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, status.error);
EXPECT_EQ(42, status.pos);
EXPECT_EQ(42u, status.pos);
EXPECT_EQ("", out);
}
......@@ -1605,8 +1629,8 @@ TEST_F(JsonParserTest, Unicode_ParseUtf8) {
TEST_F(JsonParserTest, UnprocessedInputRemainsError) {
// Trailing junk after the valid JSON.
std::string json = "{\"foo\": 3.1415} junk";
int64_t junk_idx = json.find("junk");
EXPECT_GT(junk_idx, 0);
size_t junk_idx = json.find("junk");
EXPECT_NE(junk_idx, std::string::npos);
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, log_.status().error);
EXPECT_EQ(junk_idx, log_.status().pos);
......@@ -1658,8 +1682,7 @@ TEST_F(JsonParserTest, StackLimitExceededError_AboveLimit) {
std::string exceeded = MakeNestedJson(301);
ParseJSON(GetTestPlatform(), SpanFrom(exceeded), &log_);
EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error);
EXPECT_EQ(static_cast<std::ptrdiff_t>(strlen("{\"foo\":") * 301),
log_.status().pos);
EXPECT_EQ(strlen("{\"foo\":") * 301, log_.status().pos);
}
TEST_F(JsonParserTest, StackLimitExceededError_WayAboveLimit) {
......@@ -1667,15 +1690,14 @@ TEST_F(JsonParserTest, StackLimitExceededError_WayAboveLimit) {
std::string far_out = MakeNestedJson(320);
ParseJSON(GetTestPlatform(), SpanFrom(far_out), &log_);
EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error);
EXPECT_EQ(static_cast<std::ptrdiff_t>(strlen("{\"foo\":") * 301),
log_.status().pos);
EXPECT_EQ(strlen("{\"foo\":") * 301, log_.status().pos);
}
TEST_F(JsonParserTest, NoInputError) {
std::string json = "";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_NO_INPUT, log_.status().error);
EXPECT_EQ(0, log_.status().pos);
EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......@@ -1683,7 +1705,7 @@ TEST_F(JsonParserTest, InvalidTokenError) {
std::string json = "|";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_INVALID_TOKEN, log_.status().error);
EXPECT_EQ(0, log_.status().pos);
EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......@@ -1692,7 +1714,7 @@ TEST_F(JsonParserTest, InvalidNumberError) {
std::string json = "1E9223372036854775807";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_INVALID_NUMBER, log_.status().error);
EXPECT_EQ(0, log_.status().pos);
EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......@@ -1701,7 +1723,7 @@ TEST_F(JsonParserTest, InvalidStringError) {
std::string json = "\"foo\\x22\"";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_INVALID_STRING, log_.status().error);
EXPECT_EQ(0, log_.status().pos);
EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......@@ -1709,7 +1731,7 @@ TEST_F(JsonParserTest, UnexpectedArrayEndError) {
std::string json = "[1,2,]";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, log_.status().error);
EXPECT_EQ(5, log_.status().pos);
EXPECT_EQ(5u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......@@ -1718,7 +1740,7 @@ TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) {
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED,
log_.status().error);
EXPECT_EQ(5, log_.status().pos);
EXPECT_EQ(5u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......@@ -1727,7 +1749,7 @@ TEST_F(JsonParserTest, StringLiteralExpectedError) {
std::string json = "{\"foo\": 3.1415, \"bar: 31415e-4}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, log_.status().error);
EXPECT_EQ(16, log_.status().pos);
EXPECT_EQ(16u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......@@ -1735,7 +1757,7 @@ TEST_F(JsonParserTest, ColonExpectedError) {
std::string json = "{\"foo\", 42}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_COLON_EXPECTED, log_.status().error);
EXPECT_EQ(6, log_.status().pos);
EXPECT_EQ(6u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......@@ -1743,7 +1765,7 @@ TEST_F(JsonParserTest, UnexpectedMapEndError) {
std::string json = "{\"foo\": 42, }";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_MAP_END, log_.status().error);
EXPECT_EQ(12, log_.status().pos);
EXPECT_EQ(12u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......@@ -1752,7 +1774,7 @@ TEST_F(JsonParserTest, CommaOrMapEndExpectedError) {
std::string json = "{\"foo\": 3.1415: \"bar\": 0}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED, log_.status().error);
EXPECT_EQ(14, log_.status().pos);
EXPECT_EQ(14u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......@@ -1760,7 +1782,7 @@ TEST_F(JsonParserTest, ValueExpectedError) {
std::string json = "}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, log_.status().error);
EXPECT_EQ(0, log_.status().pos);
EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str());
}
......
......@@ -137,7 +137,7 @@ std::unique_ptr<Value> parseValue(
}
case cbor::CBORTokenTag::STRING16: {
span<uint8_t> wire = tokenizer->GetString16WireRep();
DCHECK_EQ(wire.size() & 1, 0);
DCHECK_EQ(wire.size() & 1, 0u);
std::unique_ptr<Value> value = StringValue::create(StringUtil::fromUTF16(
reinterpret_cast<const uint16_t*>(wire.data()), wire.size() / 2));
tokenizer->Next();
......
......@@ -6,6 +6,7 @@
// found in the LICENSE file.
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
......@@ -178,9 +179,9 @@ void WriteBytesMostSignificantByteFirst(T v, C* out) {
// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
template <typename T>
T ReadBytesMostSignificantByteFirst(span<uint8_t> in) {
assert(static_cast<std::size_t>(in.size()) >= sizeof(T));
assert(in.size() >= sizeof(T));
T result = 0;
for (std::size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes)
for (size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes)
result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8);
return result;
}
......@@ -192,6 +193,7 @@ namespace internals {
// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
// (e.g. for BYTE_STRING).
// If successful, returns the number of bytes read. Otherwise returns -1.
// TODO(johannes): change return type to size_t and use 0 for error.
int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
if (bytes.empty())
return -1;
......@@ -214,21 +216,21 @@ int8_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
}
if (additional_information == kAdditionalInformation2Bytes) {
// Values 256-65535: 1 initial byte + 2 bytes payload.
if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint16_t))
if (bytes.size() < 1 + sizeof(uint16_t))
return -1;
*value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1));
return 3;
}
if (additional_information == kAdditionalInformation4Bytes) {
// 32 bit uint: 1 initial byte + 4 bytes payload.
if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint32_t))
if (bytes.size() < 1 + sizeof(uint32_t))
return -1;
*value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1));
return 5;
}
if (additional_information == kAdditionalInformation8Bytes) {
// 64 bit uint: 1 initial byte + 8 bytes payload.
if (static_cast<std::size_t>(bytes.size()) < 1 + sizeof(uint64_t))
if (bytes.size() < 1 + sizeof(uint64_t))
return -1;
*value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1));
return 9;
......@@ -376,7 +378,7 @@ void EncodeString8(span<uint8_t> in, std::string* out) {
template <typename C>
void EncodeFromLatin1Tmpl(span<uint8_t> latin1, C* out) {
for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) {
for (size_t ii = 0; ii < latin1.size(); ++ii) {
if (latin1[ii] <= 127)
continue;
// If there's at least one non-ASCII char, convert to UTF8.
......@@ -439,12 +441,12 @@ void EncodeBinary(span<uint8_t> in, std::string* out) {
// A double is encoded with a specific initial byte
// (kInitialByteForDouble) plus the 64 bits of payload for its value.
constexpr std::ptrdiff_t kEncodedDoubleSize = 1 + sizeof(uint64_t);
constexpr size_t kEncodedDoubleSize = 1 + sizeof(uint64_t);
// An envelope is encoded with a specific initial byte
// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32
// bit wide length, plus a 32 bit length for that string.
constexpr std::ptrdiff_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t);
constexpr size_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t);
template <typename C>
void EncodeDoubleTmpl(double value, C* out) {
......@@ -470,7 +472,7 @@ void EncodeDouble(double value, std::string* out) {
// =============================================================================
template <typename C>
void EncodeStartTmpl(C* out, std::size_t* byte_size_pos) {
void EncodeStartTmpl(C* out, size_t* byte_size_pos) {
assert(*byte_size_pos == 0);
out->push_back(kInitialByteForEnvelope);
out->push_back(kInitialByteFor32BitLengthByteString);
......@@ -487,7 +489,7 @@ void EnvelopeEncoder::EncodeStart(std::string* out) {
}
template <typename C>
bool EncodeStopTmpl(C* out, std::size_t* byte_size_pos) {
bool EncodeStopTmpl(C* out, size_t* byte_size_pos) {
assert(*byte_size_pos != 0);
// The byte size is the size of the payload, that is, all the
// bytes that were written past the byte size position itself.
......@@ -664,10 +666,17 @@ Status CBORTokenizer::Status() const {
return status_;
}
// The following accessor functions ::GetInt32, ::GetDouble,
// ::GetString8, ::GetString16WireRep, ::GetBinary, ::GetEnvelopeContents
// assume that a particular token was recognized in ::ReadNextToken.
// That's where all the error checking is done. By design,
// the accessors (assuming the token was recognized) never produce
// an error.
int32_t CBORTokenizer::GetInt32() const {
assert(token_tag_ == CBORTokenTag::INT32);
// The range checks happen in ::ReadNextToken().
return static_cast<uint32_t>(
return static_cast<int32_t>(
token_start_type_ == MajorType::UNSIGNED
? token_start_internal_value_
: -static_cast<int64_t>(token_start_internal_value_) - 1);
......@@ -686,28 +695,55 @@ double CBORTokenizer::GetDouble() const {
span<uint8_t> CBORTokenizer::GetString8() const {
assert(token_tag_ == CBORTokenTag::STRING8);
auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
auto length = static_cast<size_t>(token_start_internal_value_);
return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
}
span<uint8_t> CBORTokenizer::GetString16WireRep() const {
assert(token_tag_ == CBORTokenTag::STRING16);
auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
auto length = static_cast<size_t>(token_start_internal_value_);
return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
}
span<uint8_t> CBORTokenizer::GetBinary() const {
assert(token_tag_ == CBORTokenTag::BINARY);
auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
auto length = static_cast<size_t>(token_start_internal_value_);
return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
}
span<uint8_t> CBORTokenizer::GetEnvelopeContents() const {
assert(token_tag_ == CBORTokenTag::ENVELOPE);
auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
auto length = static_cast<size_t>(token_start_internal_value_);
return bytes_.subspan(status_.pos + kEncodedEnvelopeHeaderSize, length);
}
// All error checking happens in ::ReadNextToken, so that the accessors
// can avoid having to carry an error return value.
//
// With respect to checking the encoded lengths of strings, arrays, etc:
// On the wire, CBOR uses 1,2,4, and 8 byte unsigned integers, so
// we initially read them as uint64_t, usually into token_start_internal_value_.
//
// However, since these containers have a representation on the machine,
// we need to do corresponding size computations on the input byte array,
// output span (e.g. the payload for a string), etc., and size_t is
// machine specific (in practice either 32 bit or 64 bit).
//
// Further, we must avoid overflowing size_t. Therefore, we use this
// kMaxValidLength constant to:
// - Reject values that are larger than the architecture specific
// max size_t (differs between 32 bit and 64 bit arch).
// - Reserve at least one bit so that we can check against overflows
// when adding lengths (array / string length / etc.); we do this by
// ensuring that the inputs to an addition are <= kMaxValidLength,
// and then checking whether the sum went past it.
//
// See also
// https://chromium.googlesource.com/chromium/src/+/master/docs/security/integer-semantics.md
static const uint64_t kMaxValidLength =
std::min<uint64_t>(std::numeric_limits<uint64_t>::max() >> 2,
std::numeric_limits<size_t>::max());
void CBORTokenizer::ReadNextToken(bool enter_envelope) {
if (enter_envelope) {
status_.pos += kEncodedEnvelopeHeaderSize;
......@@ -720,6 +756,7 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
token_tag_ = CBORTokenTag::DONE;
return;
}
const size_t remaining_bytes = bytes_.size() - status_.pos;
switch (bytes_[status_.pos]) {
case kStopByte:
SetToken(CBORTokenTag::STOP, 1);
......@@ -740,21 +777,26 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
SetToken(CBORTokenTag::NULL_VALUE, 1);
return;
case kExpectedConversionToBase64Tag: { // BINARY
int8_t bytes_read = internals::ReadTokenStart(
const int8_t bytes_read = internals::ReadTokenStart(
bytes_.subspan(status_.pos + 1), &token_start_type_,
&token_start_internal_value_);
int64_t token_byte_length = 1 + bytes_read + token_start_internal_value_;
if (-1 == bytes_read || token_start_type_ != MajorType::BYTE_STRING ||
status_.pos + token_byte_length > bytes_.size()) {
if (bytes_read < 0 || token_start_type_ != MajorType::BYTE_STRING ||
token_start_internal_value_ > kMaxValidLength) {
SetError(Error::CBOR_INVALID_BINARY);
return;
}
SetToken(CBORTokenTag::BINARY,
static_cast<std::ptrdiff_t>(token_byte_length));
const uint64_t token_byte_length = token_start_internal_value_ +
/* tag before token start: */ 1 +
/* token start: */ bytes_read;
if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_BINARY);
return;
}
SetToken(CBORTokenTag::BINARY, static_cast<size_t>(token_byte_length));
return;
}
case kInitialByteForDouble: { // DOUBLE
if (status_.pos + kEncodedDoubleSize > bytes_.size()) {
if (kEncodedDoubleSize > remaining_bytes) {
SetError(Error::CBOR_INVALID_DOUBLE);
return;
}
......@@ -762,7 +804,7 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
return;
}
case kInitialByteForEnvelope: { // ENVELOPE
if (status_.pos + kEncodedEnvelopeHeaderSize > bytes_.size()) {
if (kEncodedEnvelopeHeaderSize > remaining_bytes) {
SetError(Error::CBOR_INVALID_ENVELOPE);
return;
}
......@@ -774,26 +816,30 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
// Read the length of the byte string.
token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>(
bytes_.subspan(status_.pos + 2));
// Make sure the payload is contained within the message.
if (token_start_internal_value_ + kEncodedEnvelopeHeaderSize +
status_.pos >
static_cast<std::size_t>(bytes_.size())) {
if (token_start_internal_value_ > kMaxValidLength) {
SetError(Error::CBOR_INVALID_ENVELOPE);
return;
}
auto length = static_cast<std::ptrdiff_t>(token_start_internal_value_);
SetToken(CBORTokenTag::ENVELOPE, kEncodedEnvelopeHeaderSize + length);
uint64_t token_byte_length =
token_start_internal_value_ + kEncodedEnvelopeHeaderSize;
if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_ENVELOPE);
return;
}
SetToken(CBORTokenTag::ENVELOPE, static_cast<size_t>(token_byte_length));
return;
}
default: {
span<uint8_t> remainder =
bytes_.subspan(status_.pos, bytes_.size() - status_.pos);
assert(!remainder.empty());
int8_t token_start_length = internals::ReadTokenStart(
remainder, &token_start_type_, &token_start_internal_value_);
bool success = token_start_length != -1;
const int8_t token_start_length = internals::ReadTokenStart(
bytes_.subspan(status_.pos), &token_start_type_,
&token_start_internal_value_);
const bool success = token_start_length >= 0;
switch (token_start_type_) {
case MajorType::UNSIGNED: // INT32.
// INT32 is a signed int32 (int32 makes sense for the
// inspector_protocol, it's not a CBOR limitation), so we check
// against the signed max, so that the allowable values are
// 0, 1, 2, ... 2^31 - 1.
if (!success || std::numeric_limits<int32_t>::max() <
token_start_internal_value_) {
SetError(Error::CBOR_INVALID_INT32);
......@@ -801,46 +847,53 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
}
SetToken(CBORTokenTag::INT32, token_start_length);
return;
case MajorType::NEGATIVE: // INT32.
if (!success ||
std::numeric_limits<int32_t>::min() >
-static_cast<int64_t>(token_start_internal_value_) - 1) {
case MajorType::NEGATIVE: { // INT32.
// INT32 is a signed int32 (int32 makes sense for the
// inspector_protocol, it's not a CBOR limitation); in CBOR,
// the negative values for INT32 are represented as NEGATIVE,
// that is, -1 INT32 is represented as 1 << 5 | 0 (major type 1,
// additional info value 0). So here, we compute the INT32 value
// and then check it against the INT32 min.
int64_t actual_value =
-static_cast<int64_t>(token_start_internal_value_) - 1;
if (!success || actual_value < std::numeric_limits<int32_t>::min()) {
SetError(Error::CBOR_INVALID_INT32);
return;
}
SetToken(CBORTokenTag::INT32, token_start_length);
return;
}
case MajorType::STRING: { // STRING8.
if (!success) {
if (!success || token_start_internal_value_ > kMaxValidLength) {
SetError(Error::CBOR_INVALID_STRING8);
return;
}
auto length =
static_cast<std::ptrdiff_t>(token_start_internal_value_);
if (remainder.size() < token_start_length + length) {
uint64_t token_byte_length =
token_start_internal_value_ + token_start_length;
if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_STRING8);
return;
}
SetToken(CBORTokenTag::STRING8, token_start_length + length);
SetToken(CBORTokenTag::STRING8,
static_cast<size_t>(token_byte_length));
return;
}
case MajorType::BYTE_STRING: { // STRING16.
if (!success) {
SetError(Error::CBOR_INVALID_STRING16);
return;
}
auto length =
static_cast<std::ptrdiff_t>(token_start_internal_value_);
if (remainder.size() < token_start_length + length) {
// Length must be divisible by 2 since UTF16 is 2 bytes per
// character, hence the &1 check.
if (!success || token_start_internal_value_ > kMaxValidLength ||
token_start_internal_value_ & 1) {
SetError(Error::CBOR_INVALID_STRING16);
return;
}
if (length & 1) {
// Must be divisible by 2 since UTF16 is 2 bytes per character.
uint64_t token_byte_length =
token_start_internal_value_ + token_start_length;
if (token_byte_length > remaining_bytes) {
SetError(Error::CBOR_INVALID_STRING16);
return;
}
SetToken(CBORTokenTag::STRING16, token_start_length + length);
SetToken(CBORTokenTag::STRING16,
static_cast<size_t>(token_byte_length));
return;
}
case MajorType::ARRAY:
......@@ -854,8 +907,7 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) {
}
}
void CBORTokenizer::SetToken(CBORTokenTag token_tag,
std::ptrdiff_t token_byte_length) {
void CBORTokenizer::SetToken(CBORTokenTag token_tag, size_t token_byte_length) {
token_tag_ = token_tag;
token_byte_length_ = token_byte_length;
}
......@@ -889,7 +941,7 @@ bool ParseValue(int32_t stack_depth,
void ParseUTF16String(CBORTokenizer* tokenizer, StreamingParserHandler* out) {
std::vector<uint16_t> value;
span<uint8_t> rep = tokenizer->GetString16WireRep();
for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2)
for (size_t ii = 0; ii < rep.size(); ii += 2)
value.push_back((rep[ii + 1] << 8) | rep[ii]);
out->HandleString16(span<uint16_t>(value.data(), value.size()));
tokenizer->Next();
......@@ -1081,9 +1133,9 @@ Status AppendString8EntryToCBORMapTmpl(span<uint8_t> string8_key,
return tokenizer.Status();
if (tokenizer.TokenTag() != CBORTokenTag::ENVELOPE)
return Status(Error::CBOR_INVALID_ENVELOPE, 0);
std::ptrdiff_t envelope_size = tokenizer.GetEnvelopeContents().size();
std::size_t old_size = cbor->size();
if (old_size != std::size_t(envelope_size) + kEncodedEnvelopeHeaderSize)
size_t envelope_size = tokenizer.GetEnvelopeContents().size();
size_t old_size = cbor->size();
if (old_size != envelope_size + kEncodedEnvelopeHeaderSize)
return Status(Error::CBOR_INVALID_ENVELOPE, 0);
if (envelope_size == 0 ||
(tokenizer.GetEnvelopeContents()[0] != EncodeIndefiniteLengthMapStart()))
......@@ -1094,10 +1146,10 @@ Status AppendString8EntryToCBORMapTmpl(span<uint8_t> string8_key,
EncodeString8(string8_key, cbor);
EncodeString8(string8_value, cbor);
cbor->push_back(EncodeStop());
std::size_t new_envelope_size = envelope_size + (cbor->size() - old_size);
size_t new_envelope_size = envelope_size + (cbor->size() - old_size);
if (new_envelope_size > std::numeric_limits<uint32_t>::max())
return Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, 0);
std::size_t size_pos = cbor->size() - new_envelope_size - sizeof(uint32_t);
size_t size_pos = cbor->size() - new_envelope_size - sizeof(uint32_t);
uint8_t* out = reinterpret_cast<uint8_t*>(&cbor->at(size_pos));
*(out++) = (new_envelope_size >> 24) & 0xff;
*(out++) = (new_envelope_size >> 16) & 0xff;
......@@ -1175,7 +1227,7 @@ void Base64Encode(const span<uint8_t>& in, C* out) {
// The following three cases are based on the tables in the example
// section in https://en.wikipedia.org/wiki/Base64. We process three
// input bytes at a time, emitting 4 output bytes at a time.
std::ptrdiff_t ii = 0;
size_t ii = 0;
// While possible, process three input bytes.
for (; ii + 3 <= in.size(); ii += 3) {
......@@ -1280,7 +1332,7 @@ class JSONEncoder : public StreamingParserHandler {
return;
state_.top().StartElement(out_);
Emit('"');
for (std::ptrdiff_t ii = 0; ii < chars.size(); ++ii) {
for (size_t ii = 0; ii < chars.size(); ++ii) {
uint8_t c = chars[ii];
if (c == '"') {
Emit("\\\"");
......@@ -1492,7 +1544,7 @@ class JsonParser {
JsonParser(const Platform* platform, StreamingParserHandler* handler)
: platform_(platform), handler_(handler) {}
void Parse(const Char* start, std::size_t length) {
void Parse(const Char* start, size_t length) {
start_pos_ = start;
const Char* end = start + length;
const Char* tokenEnd = nullptr;
......@@ -1505,12 +1557,10 @@ class JsonParser {
}
private:
bool CharsToDouble(const uint16_t* chars,
std::size_t length,
double* result) {
bool CharsToDouble(const uint16_t* chars, size_t length, double* result) {
std::string buffer;
buffer.reserve(length + 1);
for (std::size_t ii = 0; ii < length; ++ii) {
for (size_t ii = 0; ii < length; ++ii) {
bool is_ascii = !(chars[ii] & ~0x7F);
if (!is_ascii)
return false;
......@@ -1519,7 +1569,7 @@ class JsonParser {
return platform_->StrToD(buffer.c_str(), result);
}
bool CharsToDouble(const uint8_t* chars, std::size_t length, double* result) {
bool CharsToDouble(const uint8_t* chars, size_t length, double* result) {
std::string buffer(reinterpret_cast<const char*>(chars), length);
return platform_->StrToD(buffer.c_str(), result);
}
......@@ -2062,7 +2112,8 @@ class JsonParser {
void HandleError(Error error, const Char* pos) {
assert(error != Error::OK);
if (!error_) {
handler_->HandleError(Status{error, pos - start_pos_});
handler_->HandleError(
Status{error, static_cast<size_t>(pos - start_pos_)});
error_ = true;
}
}
......
......@@ -11,6 +11,7 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <limits>
#include <memory>
#include <string>
#include <vector>
......@@ -26,13 +27,11 @@ namespace {{namespace}} {
// span - sequence of bytes
// =============================================================================
// This template is similar to std::span, which will be included in C++20. Like
// std::span it uses ptrdiff_t, which is signed (and thus a bit annoying
// sometimes when comparing with size_t), but other than this it's much simpler.
// This template is similar to std::span, which will be included in C++20.
template <typename T>
class span {
public:
using index_type = std::ptrdiff_t;
using index_type = size_t;
span() : data_(nullptr), size_(0) {}
span(const T* data, index_type size) : data_(data), size_(size) {}
......@@ -124,13 +123,13 @@ enum class Error {
// A status value with position that can be copied. The default status
// is OK. Usually, error status values should come with a valid position.
struct Status {
static constexpr std::ptrdiff_t npos() { return -1; }
static constexpr size_t npos() { return std::numeric_limits<size_t>::max(); }
bool ok() const { return error == Error::OK; }
Error error = Error::OK;
std::ptrdiff_t pos = npos();
Status(Error error, std::ptrdiff_t pos) : error(error), pos(pos) {}
size_t pos = npos();
Status(Error error, size_t pos) : error(error), pos(pos) {}
Status() = default;
// Returns a 7 bit US-ASCII string, either "OK" or an error message
......@@ -276,7 +275,7 @@ class EnvelopeEncoder {
bool EncodeStop(std::string* out);
private:
std::size_t byte_size_pos_ = 0;
size_t byte_size_pos_ = 0;
};
// =============================================================================
......@@ -400,13 +399,13 @@ class CBORTokenizer {
private:
void ReadNextToken(bool enter_envelope);
void SetToken(CBORTokenTag token, std::ptrdiff_t token_byte_length);
void SetToken(CBORTokenTag token, size_t token_byte_length);
void SetError(Error error);
span<uint8_t> bytes_;
CBORTokenTag token_tag_;
struct Status status_;
std::ptrdiff_t token_byte_length_;
size_t token_byte_length_;
MajorType token_start_type_;
uint64_t token_start_internal_value_;
};
......
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