DeserializeVarint() does not try to detect overlong varints. It just stops processing after it has consumed N_BYTES_IN_VARINT + 1
input bytes and does not consume further input bytes even when the last byte's MSB is set.
Is this the intended behavior? I do not know enough details about the protobuf specs for this situation. Maybe even the specs do not say, but I believe the official protoc fails parsing when an overlong varint is encountered. In the following code, the output is "0 11619996266903654561 3", indicating that deserialize() succeded, but protoc --decode
on the same input stream fails with "Failed to parse input."
Dummy.proto
===========
syntax = "proto3";
message Dummy {
uint64 x = 1;
uint32 y = 2;
}
test.cpp
========
#include <cstdint>
#include <iostream>
#include "Dummy.h"
using namespace std;
char encoding[] = {
'\x8', '\xa1', '\xa1', '\xa1', '\xa1', '\xa1', '\xa1', '\xa1', '\xa1', '\xa1', '\xa1', '\x10',
'\x10', '\x3'
};
class ReadBufferInterface final : public EmbeddedProto::ReadBufferInterface {
public:
ReadBufferInterface(uint8_t const* begin, uint8_t const* end)
: mBegin(begin), mEnd(end), mCur(begin) { }
uint32_t get_size() const override { return mEnd - mCur; }
uint32_t get_max_size() const override { return mEnd - mBegin; }
bool peek(uint8_t& byte) const override {
if (mCur == mEnd)
return false;
byte = *mCur;
return true;
}
void advance() override {
if (mCur != mEnd)
++mCur;
}
void advance(uint32_t const n) override {
mCur += n;
if (mCur > mEnd)
mCur = mEnd;
}
bool pop(uint8_t& byte) override {
if (mCur == mEnd)
return false;
byte = *mCur;
++mCur;
return true;
}
private:
uint8_t const* mBegin;
uint8_t const* mEnd;
uint8_t const* mCur;
}; // ReadBufferInterface
int main() {
ReadBufferInterface rbi(reinterpret_cast<uint8_t const*>(encoding),
reinterpret_cast<uint8_t const*>(encoding) + sizeof(encoding));
Dummy dummy;
auto error = dummy.deserialize(rbi);
cout << static_cast<uint16_t>(error) << ' ' << dummy.x() << ' ' << dummy.y() << '\n';
return 0;
};