Index: base/pickle.cc |
diff --git a/base/pickle.cc b/base/pickle.cc |
index 7c8ffed4a266c270bf4256402312d353536157bf..489c7f890a7168868a018248ef4fd912079cec22 100644 |
--- a/base/pickle.cc |
+++ b/base/pickle.cc |
@@ -7,6 +7,7 @@ |
#include <stdlib.h> |
#include <algorithm> // for max() |
+#include <limits> |
#include "base/bits.h" |
#include "base/macros.h" |
@@ -338,17 +339,41 @@ size_t Pickle::GetTotalAllocatedSize() const { |
const char* Pickle::FindNext(size_t header_size, |
const char* start, |
const char* end) { |
+ size_t pickle_size = 0; |
+ if (!PeekNext(header_size, start, end, &pickle_size)) |
+ return NULL; |
+ |
+ if (pickle_size > static_cast<size_t>(end - start)) |
+ return NULL; |
+ |
+ return start + pickle_size; |
+} |
+ |
+// static |
+bool Pickle::PeekNext(size_t header_size, |
+ const char* start, |
+ const char* end, |
+ size_t* pickle_size) { |
DCHECK_EQ(header_size, bits::Align(header_size, sizeof(uint32))); |
+ DCHECK_GE(header_size, sizeof(Header)); |
DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit)); |
size_t length = static_cast<size_t>(end - start); |
if (length < sizeof(Header)) |
- return NULL; |
+ return false; |
const Header* hdr = reinterpret_cast<const Header*>(start); |
- if (length < header_size || length - header_size < hdr->payload_size) |
- return NULL; |
- return start + header_size + hdr->payload_size; |
+ if (length < header_size) |
+ return false; |
+ |
+ if (hdr->payload_size > std::numeric_limits<size_t>::max() - header_size) { |
+ // If payload_size causes an overflow, we return maximum possible |
+ // pickle size to indicate that. |
+ *pickle_size = std::numeric_limits<size_t>::max(); |
+ } else { |
+ *pickle_size = header_size + hdr->payload_size; |
+ } |
+ return true; |
} |
template <size_t length> void Pickle::WriteBytesStatic(const void* data) { |