Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Unified Diff: third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp

Issue 2252723003: Fix fragmented image signature handling (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: minor cleanup Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTestWoPlatform.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp
index 874b7d06e12a3f288ac7c7d56ac845b6f1a6bcfa..1d53d47486886a9f6ab030f6ae4063d2b27aebd7 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp
@@ -107,12 +107,57 @@ std::unique_ptr<ImageDecoder> ImageDecoder::create(SniffResult sniffResult, Alph
return nullptr;
}
+namespace {
Peter Kasting 2016/08/16 20:12:25 Instead of adding all this, why not just use FastS
f(malita) 2016/08/16 21:54:03 I wasn't familiar with FastSharedBufferReader, goo
+
+constexpr size_t kLongestSignatureLength = sizeof("RIFF????WEBPVP") - 1;
+static_assert(kLongestSignatureLength == 14, "kLongestSignatureLength mismatch");
+
+// Offers contiguous access to the first LEN bytes in the buffer.
+// If the first segment is large enough to hold all the requested data, we use a pointer to
+// the actual segment data.
+// Otherwise, we copy/consolidate the data in a local buffer.
+template <typename T, size_t LEN>
+class SpeculativeSegmentReader {
+ STACK_ALLOCATED();
+public:
+ SpeculativeSegmentReader(const T& data, size_t (*accessSegment)(const T&, const char*&, size_t))
+ {
+ m_dataLen = accessSegment(data, m_data, 0);
+ if (!m_dataLen || m_dataLen >= LEN) {
+ // We either don't have any data, or the first segment is large enough.
+ // Either way, we don't need a copy: just use the actual/contiguous segment data.
+ return;
+ }
+
+ // The signature is fragmented: we need to make a copy.
+ std::copy(m_data, m_data + m_dataLen, m_buffer);
+ m_data = m_buffer;
+
+ do {
+ const char* segmentData;
+ const size_t segmentLen = accessSegment(data, segmentData, m_dataLen);
+ if (!segmentLen)
+ break;
+ const size_t usableLen = std::min(segmentLen, LEN - m_dataLen);
+ std::copy(segmentData, segmentData + usableLen, m_buffer + m_dataLen);
+ m_dataLen += usableLen;
+ } while (m_dataLen < LEN);
+ }
+
+ const char* data() const { return m_data; }
+ size_t dataLen() const { return m_dataLen; }
+
+private:
+ const char* m_data;
+ size_t m_dataLen;
+ char m_buffer[LEN];
+};
+
+} // anonymous ns
+
ImageDecoder::SniffResult ImageDecoder::determineImageType(const char* contents, size_t length)
{
- const size_t longestSignatureLength = sizeof("RIFF????WEBPVP") - 1;
- DCHECK_EQ(14u, longestSignatureLength);
-
- if (length < longestSignatureLength)
+ if (length < kLongestSignatureLength)
return SniffResult::InsufficientData;
if (matchesJPEGSignature(contents))
return SniffResult::JPEG;
@@ -131,16 +176,20 @@ ImageDecoder::SniffResult ImageDecoder::determineImageType(const char* contents,
ImageDecoder::SniffResult ImageDecoder::determineImageType(const SharedBuffer& data)
{
- const char* contents;
- const size_t length = data.getSomeData<size_t>(contents);
- return determineImageType(contents, length);
+ const SpeculativeSegmentReader<SharedBuffer, kLongestSignatureLength> sniffer(data,
+ [] (const SharedBuffer& data, const char*& segmentData, size_t offset) -> size_t {
+ return data.getSomeData<size_t>(segmentData, offset);
+ });
+ return determineImageType(sniffer.data(), sniffer.dataLen());
}
ImageDecoder::SniffResult ImageDecoder::determineImageType(const SegmentReader& data)
{
- const char* contents;
- const size_t length = data.getSomeData(contents, 0);
- return determineImageType(contents, length);
+ const SpeculativeSegmentReader<SegmentReader, kLongestSignatureLength> sniffer(data,
+ [] (const SegmentReader& data, const char*& segmentData, size_t offset) -> size_t {
+ return data.getSomeData(segmentData, offset);
+ });
+ return determineImageType(sniffer.data(), sniffer.dataLen());
}
size_t ImageDecoder::frameCount()
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTestWoPlatform.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698