aboutsummaryrefslogtreecommitdiff
path: root/pw_protobuf/codegen_message_test.cc
diff options
context:
space:
mode:
authorScott James Remnant <keybuk@google.com>2022-04-28 17:41:22 -0700
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-04-29 06:52:53 +0000
commitfadddbc57c8e58e0e3f022743a22b68a3ccde94c (patch)
treebdba73cd041626c1f4fd0b12f76adb1c0c2a6098 /pw_protobuf/codegen_message_test.cc
parent200aeb31d64d88ebc0219e028fbabd6d1d279035 (diff)
downloadpigweed-fadddbc57c8e58e0e3f022743a22b68a3ccde94c.tar.gz
pw_protobuf: Check fields don't exceed message bounds
Change-Id: Ic809af6d5d8903a8896d5cb3073505cddcbba8c0 Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/92762 Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com> Pigweed-Auto-Submit: Scott James Remnant <keybuk@google.com> Reviewed-by: Keir Mierle <keir@google.com>
Diffstat (limited to 'pw_protobuf/codegen_message_test.cc')
-rw-r--r--pw_protobuf/codegen_message_test.cc81
1 files changed, 81 insertions, 0 deletions
diff --git a/pw_protobuf/codegen_message_test.cc b/pw_protobuf/codegen_message_test.cc
index a5c0d72da..be026e978 100644
--- a/pw_protobuf/codegen_message_test.cc
+++ b/pw_protobuf/codegen_message_test.cc
@@ -17,6 +17,7 @@
#include "gtest/gtest.h"
#include "pw_preprocessor/compiler.h"
+#include "pw_protobuf/internal/codegen.h"
#include "pw_status/status.h"
#include "pw_status/status_with_size.h"
#include "pw_stream/memory_stream.h"
@@ -943,6 +944,49 @@ TEST(CodegenMessage, ReadNestedForcedCallback) {
ASSERT_EQ(status, OkStatus());
}
+class BreakableDecoder : public KeyValuePair::StreamDecoder {
+ public:
+ constexpr BreakableDecoder(stream::Reader& reader) : StreamDecoder(reader) {}
+
+ Status Read(KeyValuePair::Message& message,
+ std::span<const MessageField> table) {
+ return ::pw::protobuf::StreamDecoder::Read(
+ std::as_writable_bytes(std::span(&message, 1)), table);
+ }
+};
+
+TEST(CodegenMessage, DISABLED_ReadDoesNotOverrun) {
+ // Deliberately construct a message table that attempts to violate the bounds
+ // of the structure. We're not testing that a developer can't do this, rather
+ // that the protobuf decoder can't be exploited in this way.
+ constexpr MessageField kMessageFields[] = {
+ {1,
+ WireType::kDelimited,
+ sizeof(std::byte),
+ static_cast<VarintType>(0),
+ false,
+ false,
+ false,
+ 0,
+ sizeof(KeyValuePair::Message) * 2,
+ {}},
+ };
+
+ // clang-format off
+ constexpr uint8_t proto_data[] = {
+ // id=1, len=9,
+ 0x0a, 0x08, 'd', 'o', 'n', 't', 'e', 'a', 't', 'm', 'e',
+ };
+ // clang-format on
+
+ stream::MemoryReader reader(std::as_bytes(std::span(proto_data)));
+ BreakableDecoder decoder(reader);
+
+ KeyValuePair::Message message{};
+ // ASSERT_CRASH
+ std::ignore = decoder.Read(message, kMessageFields);
+}
+
TEST(CodegenMessage, Write) {
constexpr uint8_t pigweed_data[] = {
0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
@@ -1561,6 +1605,43 @@ TEST(CodegenMessage, WriteNestedForcedCallback) {
0);
}
+class BreakableEncoder : public KeyValuePair::MemoryEncoder {
+ public:
+ constexpr BreakableEncoder(ByteSpan buffer)
+ : KeyValuePair::MemoryEncoder(buffer) {}
+
+ Status Write(const KeyValuePair::Message& message,
+ std::span<const MessageField> table) {
+ return ::pw::protobuf::StreamEncoder::Write(
+ std::as_bytes(std::span(&message, 1)), table);
+ }
+};
+
+TEST(CodegenMessage, DISABLED_WriteDoesNotOverrun) {
+ // Deliberately construct a message table that attempts to violate the bounds
+ // of the structure. We're not testing that a developer can't do this, rather
+ // that the protobuf encoder can't be exploited in this way.
+ constexpr MessageField kMessageFields[] = {
+ {1,
+ WireType::kDelimited,
+ sizeof(std::byte),
+ static_cast<VarintType>(0),
+ false,
+ false,
+ false,
+ 0,
+ sizeof(KeyValuePair::Message) * 2,
+ {}},
+ };
+
+ std::byte encode_buffer[64];
+
+ BreakableEncoder encoder(encode_buffer);
+ KeyValuePair::Message message{};
+ // ASSERT_CRASH
+ std::ignore = encoder.Write(message, kMessageFields);
+}
+
// The following tests cover using the codegen struct Message and callbacks in
// different ways.