From ef81390393ef5fed1ba168cff081d459eed9f260 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Wed, 1 Mar 2017 00:32:20 -0800 Subject: Fix infinite loops in CPDF_MeshStream. BUG=chromium:690501 Change-Id: I74b09d90a8082554a67f737eb6adc3bff82ed93e Reviewed-on: https://pdfium-review.googlesource.com/2889 Commit-Queue: dsinclair Reviewed-by: dsinclair --- core/fpdfapi/page/cpdf_meshstream.cpp | 37 ++++++++++++++++++++------ core/fpdfapi/page/cpdf_meshstream.h | 8 +++++- core/fpdfapi/page/cpdf_streamcontentparser.cpp | 7 ++++- core/fpdfapi/render/cpdf_renderstatus.cpp | 18 ++++++++++--- 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/core/fpdfapi/page/cpdf_meshstream.cpp b/core/fpdfapi/page/cpdf_meshstream.cpp index 75069cab7f..24ef9b271e 100644 --- a/core/fpdfapi/page/cpdf_meshstream.cpp +++ b/core/fpdfapi/page/cpdf_meshstream.cpp @@ -154,6 +154,18 @@ bool CPDF_MeshStream::Load() { return true; } +bool CPDF_MeshStream::CanReadFlag() const { + return m_BitStream.BitsRemaining() >= m_nFlagBits; +} + +bool CPDF_MeshStream::CanReadCoords() const { + return m_BitStream.BitsRemaining() / 2 >= m_nCoordBits; +} + +bool CPDF_MeshStream::CanReadColor() const { + return m_BitStream.BitsRemaining() / m_nComponentBits >= m_nComponents; +} + uint32_t CPDF_MeshStream::ReadFlag() { ASSERT(ShouldCheckBitsPerFlag(m_type)); return m_BitStream.GetBits(m_nFlagBits) & 0x03; @@ -209,26 +221,35 @@ std::tuple CPDF_MeshStream::ReadColor() { return std::tuple(r, g, b); } -CPDF_MeshVertex CPDF_MeshStream::ReadVertex(const CFX_Matrix& pObject2Bitmap, - uint32_t* flag) { +bool CPDF_MeshStream::ReadVertex(const CFX_Matrix& pObject2Bitmap, + CPDF_MeshVertex* vertex, + uint32_t* flag) { + if (!CanReadFlag()) + return false; *flag = ReadFlag(); - CPDF_MeshVertex vertex; - vertex.position = pObject2Bitmap.Transform(ReadCoords()); - std::tie(vertex.r, vertex.g, vertex.b) = ReadColor(); - m_BitStream.ByteAlign(); + if (!CanReadCoords()) + return false; + vertex->position = pObject2Bitmap.Transform(ReadCoords()); - return vertex; + if (!CanReadColor()) + return false; + std::tie(vertex->r, vertex->g, vertex->b) = ReadColor(); + m_BitStream.ByteAlign(); + return true; } bool CPDF_MeshStream::ReadVertexRow(const CFX_Matrix& pObject2Bitmap, int count, CPDF_MeshVertex* vertex) { for (int i = 0; i < count; i++) { - if (m_BitStream.IsEOF()) + if (m_BitStream.IsEOF() || !CanReadCoords()) return false; vertex[i].position = pObject2Bitmap.Transform(ReadCoords()); + if (!CanReadColor()) + return false; + std::tie(vertex[i].r, vertex[i].g, vertex[i].b) = ReadColor(); m_BitStream.ByteAlign(); } diff --git a/core/fpdfapi/page/cpdf_meshstream.h b/core/fpdfapi/page/cpdf_meshstream.h index 24f1d66cfd..d40de4a013 100644 --- a/core/fpdfapi/page/cpdf_meshstream.h +++ b/core/fpdfapi/page/cpdf_meshstream.h @@ -42,11 +42,17 @@ class CPDF_MeshStream { bool Load(); + bool CanReadFlag() const; + bool CanReadCoords() const; + bool CanReadColor() const; + uint32_t ReadFlag(); CFX_PointF ReadCoords(); std::tuple ReadColor(); - CPDF_MeshVertex ReadVertex(const CFX_Matrix& pObject2Bitmap, uint32_t* flag); + bool ReadVertex(const CFX_Matrix& pObject2Bitmap, + CPDF_MeshVertex* vertex, + uint32_t* flag); bool ReadVertexRow(const CFX_Matrix& pObject2Bitmap, int count, CPDF_MeshVertex* vertex); diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.cpp b/core/fpdfapi/page/cpdf_streamcontentparser.cpp index d8e1c1e15d..6211b6a4dd 100644 --- a/core/fpdfapi/page/cpdf_streamcontentparser.cpp +++ b/core/fpdfapi/page/cpdf_streamcontentparser.cpp @@ -98,8 +98,11 @@ CFX_FloatRect GetShadingBBox(CPDF_ShadingPattern* pShading, while (!stream.BitStream()->IsEOF()) { uint32_t flag = 0; - if (type != kLatticeFormGouraudTriangleMeshShading) + if (type != kLatticeFormGouraudTriangleMeshShading) { + if (!stream.CanReadFlag()) + break; flag = stream.ReadFlag(); + } if (!bGouraud && flag) { point_count -= 4; @@ -107,6 +110,8 @@ CFX_FloatRect GetShadingBBox(CPDF_ShadingPattern* pShading, } for (int i = 0; i < point_count; i++) { + if (!stream.CanReadCoords()) + break; CFX_PointF origin = stream.ReadCoords(); if (bStarted) { rect.UpdateRect(origin.x, origin.y); diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp index 1e67eaba55..9022212ecc 100644 --- a/core/fpdfapi/render/cpdf_renderstatus.cpp +++ b/core/fpdfapi/render/cpdf_renderstatus.cpp @@ -487,13 +487,17 @@ void DrawFreeGouraudShading( FXSYS_memset(triangle, 0, sizeof(triangle)); while (!stream.BitStream()->IsEOF()) { + CPDF_MeshVertex vertex; uint32_t flag; - CPDF_MeshVertex vertex = stream.ReadVertex(*pObject2Bitmap, &flag); + if (!stream.ReadVertex(*pObject2Bitmap, &vertex, &flag)) + return; + if (flag == 0) { triangle[0] = vertex; for (int j = 1; j < 3; j++) { uint32_t tflag; - triangle[j] = stream.ReadVertex(*pObject2Bitmap, &tflag); + if (!stream.ReadVertex(*pObject2Bitmap, &triangle[j], &tflag)) + return; } } else { if (flag == 1) @@ -831,6 +835,8 @@ void DrawCoonPatchMeshes( CFX_PointF coords[16]; int point_count = type == kTensorProductPatchMeshShading ? 16 : 12; while (!stream.BitStream()->IsEOF()) { + if (!stream.CanReadFlag()) + break; uint32_t flag = stream.ReadFlag(); int iStartPoint = 0, iStartColor = 0, i = 0; if (flag) { @@ -846,10 +852,16 @@ void DrawCoonPatchMeshes( tempColors[1] = patch.patch_colors[(flag + 1) % 4]; FXSYS_memcpy(patch.patch_colors, tempColors, sizeof(Coon_Color) * 2); } - for (i = iStartPoint; i < point_count; i++) + for (i = iStartPoint; i < point_count; i++) { + if (!stream.CanReadCoords()) + break; coords[i] = pObject2Bitmap->Transform(stream.ReadCoords()); + } for (i = iStartColor; i < 4; i++) { + if (!stream.CanReadColor()) + break; + FX_FLOAT r; FX_FLOAT g; FX_FLOAT b; -- cgit v1.2.3