Do an additional check before patching bad JPEG headers.
Make sure the SOFn marker is 5 bytes before the bad dimension.
BUG=chromium:86459
Change-Id: I744c1bd8b2af1c6e979a2401679e0f3198d22e32
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/56530
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcodec/jpeg/jpegmodule.cpp b/core/fxcodec/jpeg/jpegmodule.cpp
index b7a4c31..9ba2e3e 100644
--- a/core/fxcodec/jpeg/jpegmodule.cpp
+++ b/core/fxcodec/jpeg/jpegmodule.cpp
@@ -250,6 +250,9 @@
// Can only be called inside a jpeg_read_header() setjmp handler.
bool HasKnownBadHeaderWithInvalidHeight() const;
+ // Is a JPEG SOFn marker, which is defined as 0xff, 0xc[0-9a-f].
+ bool IsSofSegment(int marker_offset) const;
+
// Patch up the in-memory JPEG header for known bad JPEGs.
void PatchUpKnownBadHeaderWithInvalidHeight();
@@ -258,6 +261,9 @@
uint8_t* GetWritableSrcData();
+ // Before |kKnownBadHeaderWithInvalidHeightByteOffsetStart|.
+ static const size_t kSofMarkerByteOffset = 5;
+
static const int kKnownBadHeaderWithInvalidHeightByteOffsetStart = 163;
uint32_t m_nDefaultScaleDenom = 1;
@@ -425,6 +431,11 @@
if (m_SrcSpan.size() <= kKnownBadHeaderWithInvalidHeightByteOffsetStart + 3)
return false;
+ if (!IsSofSegment(kKnownBadHeaderWithInvalidHeightByteOffsetStart -
+ kSofMarkerByteOffset)) {
+ return false;
+ }
+
const uint8_t* pHeaderDimensions =
&m_SrcSpan[kKnownBadHeaderWithInvalidHeightByteOffsetStart];
uint8_t nExpectedWidthByte1 = (m_OrigWidth >> 8) & 0xff;
@@ -435,6 +446,12 @@
pHeaderDimensions[3] == nExpectedWidthByte2;
}
+bool JpegDecoder::IsSofSegment(int marker_offset) const {
+ const uint8_t* pHeaderMarker = &m_SrcSpan[marker_offset];
+ return pHeaderMarker[0] == 0xff && pHeaderMarker[1] >= 0xc0 &&
+ pHeaderMarker[1] <= 0xcf;
+}
+
void JpegDecoder::PatchUpKnownBadHeaderWithInvalidHeight() {
ASSERT(m_SrcSpan.size() >
kKnownBadHeaderWithInvalidHeightByteOffsetStart + 1);