aboutsummaryrefslogtreecommitdiff
path: root/pw_varint/stream.cc
diff options
context:
space:
mode:
Diffstat (limited to 'pw_varint/stream.cc')
-rw-r--r--pw_varint/stream.cc30
1 files changed, 23 insertions, 7 deletions
diff --git a/pw_varint/stream.cc b/pw_varint/stream.cc
index 00fe1fb37..83a80de08 100644
--- a/pw_varint/stream.cc
+++ b/pw_varint/stream.cc
@@ -16,8 +16,8 @@
#include <cstddef>
#include <cstdint>
-#include <span>
+#include "pw_span/span.h"
#include "pw_status/status_with_size.h"
#include "pw_stream/stream.h"
#include "pw_varint/varint.h"
@@ -25,9 +25,9 @@
namespace pw {
namespace varint {
-StatusWithSize Read(stream::Reader& reader, int64_t* output) {
+StatusWithSize Read(stream::Reader& reader, int64_t* output, size_t max_size) {
uint64_t value = 0;
- StatusWithSize count = Read(reader, &value);
+ StatusWithSize count = Read(reader, &value, max_size);
if (!count.ok()) {
return count;
}
@@ -36,18 +36,34 @@ StatusWithSize Read(stream::Reader& reader, int64_t* output) {
return count;
}
-StatusWithSize Read(stream::Reader& reader, uint64_t* output) {
+StatusWithSize Read(stream::Reader& reader, uint64_t* output, size_t max_size) {
uint64_t value = 0;
size_t count = 0;
while (true) {
if (count >= varint::kMaxVarint64SizeBytes) {
- // Varint can't fit a uint64_t.
- return StatusWithSize::OutOfRange();
+ // Varint can't fit a uint64_t, this likely means we're reading binary
+ // data that is not actually a varint.
+ return StatusWithSize::DataLoss();
+ }
+
+ if (count >= max_size) {
+ // Varint didn't fit within the range given; return OutOfRange() if
+ // max_size was 0, but DataLoss if we were reading something we thought
+ // was going to be a varint.
+ return count > 0 ? StatusWithSize::DataLoss()
+ : StatusWithSize::OutOfRange();
}
std::byte b;
- if (auto result = reader.Read(std::span(&b, 1)); !result.ok()) {
+ if (auto result = reader.Read(span(&b, 1)); !result.ok()) {
+ if (count > 0 && result.status().IsOutOfRange()) {
+ // Status::OutOfRange on the first byte means we tried to read a varint
+ // when we reached the end of file. But after the first byte it means we
+ // failed to decode a varint we were in the middle of, and that's not
+ // a normal error condition.
+ return StatusWithSize(Status::DataLoss(), 0);
+ }
return StatusWithSize(result.status(), 0);
}