added a check for destination overflow when unstuffing
diff --git a/bbb_cape/src/bbb/packet_finder.cc b/bbb_cape/src/bbb/packet_finder.cc
index f0ea66d..dfc5784 100644
--- a/bbb_cape/src/bbb/packet_finder.cc
+++ b/bbb_cape/src/bbb/packet_finder.cc
@@ -67,9 +67,9 @@
}
bool PacketFinder::ProcessPacket() {
- uint32_t unstuffed =
- cows_unstuff(reinterpret_cast<uint32_t *>(buf_), PACKET_SIZE,
- reinterpret_cast<uint32_t *>(unstuffed_data_));
+ uint32_t unstuffed = cows_unstuff(
+ reinterpret_cast<uint32_t *>(buf_), PACKET_SIZE,
+ reinterpret_cast<uint32_t *>(unstuffed_data_), PACKET_SIZE - 4);
if (unstuffed == 0) {
LOG(WARNING, "invalid packet\n");
return false;
diff --git a/bbb_cape/src/cape/cows.c b/bbb_cape/src/cape/cows.c
index cdabaac..b896fd7 100644
--- a/bbb_cape/src/cape/cows.c
+++ b/bbb_cape/src/cape/cows.c
@@ -35,7 +35,8 @@
}
uint32_t cows_unstuff(const uint32_t *__restrict__ source, size_t source_length,
- uint32_t *__restrict__ destination) {
+ uint32_t *__restrict__ destination,
+ size_t destination_length) {
size_t source_index = 0;
size_t destination_index = 0;
uint32_t code;
@@ -50,9 +51,11 @@
for (uint32_t i = 1; i < code; ++i) {
destination[destination_index++] = source[source_index++];
+ if (destination_index > destination_length / 4) return 0;
}
if (code != UINT32_MAX && source_index != source_length / 4) {
destination[destination_index++] = 0;
+ if (destination_index > destination_length / 4) return 0;
}
}
return destination_index;
diff --git a/bbb_cape/src/cape/cows.h b/bbb_cape/src/cape/cows.h
index 3a9e6ab..442c368 100644
--- a/bbb_cape/src/cape/cows.h
+++ b/bbb_cape/src/cape/cows.h
@@ -27,12 +27,13 @@
// source_length will be rounded up a multiple of 4. That many bytes of source
// will be read.
-// Destination must be big enough to hold all source_length bytes (see
-// cows_stuff for the exact size it might be).
// source and destination both have to be 4-byte aligned.
// Returns the total number of words written to destination or 0 for error.
+// Possible errors are trying to unstuff more data than is available in source
+// or trying to write more than destination_length bytes out.
uint32_t cows_unstuff(const uint32_t *__restrict__ source, size_t source_length,
- uint32_t *__restrict__ destination);
+ uint32_t *__restrict__ destination,
+ size_t destination_length);
#ifdef __cplusplus
} // extern C