From acef5fe15d16868768989ba53639b7a7cad6fad3 Mon Sep 17 00:00:00 2001 From: thestig Date: Wed, 1 Jun 2016 13:45:03 -0700 Subject: Validate the BitsPerFlag entry in shading dictionaries. BUG=616248 Review-Url: https://codereview.chromium.org/2020183004 --- core/fpdfapi/fpdf_page/cpdf_meshstream.cpp | 42 ++++++++++++++++++--- core/fpdfapi/fpdf_page/cpdf_meshstream.h | 19 ++++++---- core/fpdfapi/fpdf_page/fpdf_page_parser.cpp | 4 +- core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp | 47 ++++++++---------------- 4 files changed, 66 insertions(+), 46 deletions(-) diff --git a/core/fpdfapi/fpdf_page/cpdf_meshstream.cpp b/core/fpdfapi/fpdf_page/cpdf_meshstream.cpp index de35541839..d3649a1fdc 100644 --- a/core/fpdfapi/fpdf_page/cpdf_meshstream.cpp +++ b/core/fpdfapi/fpdf_page/cpdf_meshstream.cpp @@ -44,17 +44,46 @@ bool IsValidBitsPerCoordinate(uint32_t x) { } } +// See PDF Reference 1.7, page 315, table 4.32. (Also table 4.34) +bool ShouldCheckBitsPerFlag(ShadingType type) { + switch (type) { + case kFreeFormGouraudTriangleMeshShading: + case kCoonsPatchMeshShading: + case kTensorProductPatchMeshShading: + return true; + default: + return false; + } +} + +// Same references as ShouldCheckBitsPerFlag() above. +bool IsValidBitsPerFlag(uint32_t x) { + switch (x) { + case 2: + case 4: + case 8: + return true; + default: + return false; + } +} + } // namespace CPDF_MeshStream::CPDF_MeshStream( + ShadingType type, const std::vector>& funcs, + CPDF_Stream* pShadingStream, CPDF_ColorSpace* pCS) - : m_funcs(funcs), m_pCS(pCS) {} + : m_type(type), + m_funcs(funcs), + m_pShadingStream(pShadingStream), + m_pCS(pCS) {} -bool CPDF_MeshStream::Load(CPDF_Stream* pShadingStream) { - m_Stream.LoadAllData(pShadingStream); +bool CPDF_MeshStream::Load() { + m_Stream.LoadAllData(m_pShadingStream); m_BitStream.Init(m_Stream.GetData(), m_Stream.GetSize()); - CPDF_Dictionary* pDict = pShadingStream->GetDict(); + CPDF_Dictionary* pDict = m_pShadingStream->GetDict(); m_nCoordBits = pDict->GetIntegerBy("BitsPerCoordinate"); if (!IsValidBitsPerCoordinate(m_nCoordBits)) return false; @@ -64,6 +93,9 @@ bool CPDF_MeshStream::Load(CPDF_Stream* pShadingStream) { return false; m_nFlagBits = pDict->GetIntegerBy("BitsPerFlag"); + if (ShouldCheckBitsPerFlag(m_type) && !IsValidBitsPerFlag(m_nFlagBits)) + return false; + uint32_t nComps = m_pCS->CountComponents(); if (nComps > 8) return false; @@ -87,6 +119,7 @@ bool CPDF_MeshStream::Load(CPDF_Stream* pShadingStream) { } uint32_t CPDF_MeshStream::GetFlag() { + ASSERT(ShouldCheckBitsPerFlag(m_type)); return m_BitStream.GetBits(m_nFlagBits) & 0x03; } @@ -105,7 +138,6 @@ void CPDF_MeshStream::GetCoords(FX_FLOAT& x, FX_FLOAT& y) { } void CPDF_MeshStream::GetColor(FX_FLOAT& r, FX_FLOAT& g, FX_FLOAT& b) { - static const int kMaxResults = 8; FX_FLOAT color_value[kMaxResults]; for (uint32_t i = 0; i < m_nComps; ++i) { color_value[i] = m_ColorMin[i] + diff --git a/core/fpdfapi/fpdf_page/cpdf_meshstream.h b/core/fpdfapi/fpdf_page/cpdf_meshstream.h index e5d37fe36b..8f47265acd 100644 --- a/core/fpdfapi/fpdf_page/cpdf_meshstream.h +++ b/core/fpdfapi/fpdf_page/cpdf_meshstream.h @@ -10,6 +10,7 @@ #include #include +#include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h" #include "core/fxcrt/include/fx_basic.h" #include "core/fxcrt/include/fx_system.h" @@ -29,12 +30,14 @@ class CPDF_Stream; class CPDF_MeshStream { public: - CPDF_MeshStream(const std::vector>& funcs, + CPDF_MeshStream(ShadingType type, + const std::vector>& funcs, + CPDF_Stream* pShadingStream, CPDF_ColorSpace* pCS); - bool Load(CPDF_Stream* pShadingStream); - uint32_t GetFlag(); + bool Load(); + uint32_t GetFlag(); void GetCoords(FX_FLOAT& x, FX_FLOAT& y); void GetColor(FX_FLOAT& r, FX_FLOAT& g, FX_FLOAT& b); @@ -44,13 +47,15 @@ class CPDF_MeshStream { CFX_Matrix* pObject2Bitmap); CFX_BitStream* BitStream() { return &m_BitStream; } - uint32_t CoordBits() const { return m_nCoordBits; } uint32_t CompBits() const { return m_nCompBits; } - uint32_t FlagBits() const { return m_nFlagBits; } uint32_t comps() const { return m_nComps; } private: + static const uint32_t kMaxResults = 8; + + const ShadingType m_type; const std::vector>& m_funcs; + CPDF_Stream* const m_pShadingStream; CPDF_ColorSpace* const m_pCS; uint32_t m_nCoordBits; uint32_t m_nCompBits; @@ -62,8 +67,8 @@ class CPDF_MeshStream { FX_FLOAT m_xmax; FX_FLOAT m_ymin; FX_FLOAT m_ymax; - FX_FLOAT m_ColorMin[8]; - FX_FLOAT m_ColorMax[8]; + FX_FLOAT m_ColorMin[kMaxResults]; + FX_FLOAT m_ColorMax[kMaxResults]; CPDF_StreamAcc m_Stream; CFX_BitStream m_BitStream; }; diff --git a/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp b/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp index ddea2e653d..0592c97176 100644 --- a/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp +++ b/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp @@ -106,8 +106,8 @@ CFX_FloatRect GetShadingBBox(CPDF_ShadingPattern* pShading, if (!pStream || !pCS) return CFX_FloatRect(0, 0, 0, 0); - CPDF_MeshStream stream(pShading->GetFuncs(), pCS); - if (!stream.Load(pStream)) + CPDF_MeshStream stream(type, pShading->GetFuncs(), pStream, pCS); + if (!stream.Load()) return CFX_FloatRect(0, 0, 0, 0); CFX_FloatRect rect; diff --git a/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp b/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp index 754394da70..7896f83459 100644 --- a/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp +++ b/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp @@ -411,8 +411,9 @@ void DrawFreeGouraudShading( int alpha) { ASSERT(pBitmap->GetFormat() == FXDIB_Argb); - CPDF_MeshStream stream(funcs, pCS); - if (!stream.Load(pShadingStream)) + CPDF_MeshStream stream(kFreeFormGouraudTriangleMeshShading, funcs, + pShadingStream, pCS); + if (!stream.Load()) return; CPDF_MeshVertex triangle[3]; @@ -450,8 +451,9 @@ void DrawLatticeGouraudShading( if (row_verts < 2) return; - CPDF_MeshStream stream(funcs, pCS); - if (!stream.Load(pShadingStream)) + CPDF_MeshStream stream(kLatticeFormGouraudTriangleMeshShading, funcs, + pShadingStream, pCS); + if (!stream.Load()) return; std::unique_ptr vertex( @@ -724,24 +726,8 @@ struct CPDF_PatchDrawer { } }; -bool CheckCoonTensorPara(const CPDF_MeshStream& stream) { - uint32_t coord = stream.CoordBits(); - bool bCoordBitsValid = - (coord == 1 || coord == 2 || coord == 4 || coord == 8 || coord == 12 || - coord == 16 || coord == 24 || coord == 32); - - uint32_t comp = stream.CompBits(); - bool bCompBitsValid = (comp == 1 || comp == 2 || comp == 4 || comp == 8 || - comp == 12 || comp == 16); - - uint32_t flag = stream.FlagBits(); - bool bFlagBitsValid = (flag == 2 || flag == 4 || flag == 8); - - return bCoordBitsValid && bCompBitsValid && bFlagBitsValid; -} - void DrawCoonPatchMeshes( - FX_BOOL bTensor, + ShadingType type, CFX_DIBitmap* pBitmap, CFX_Matrix* pObject2Bitmap, CPDF_Stream* pShadingStream, @@ -750,13 +736,13 @@ void DrawCoonPatchMeshes( int fill_mode, int alpha) { ASSERT(pBitmap->GetFormat() == FXDIB_Argb); + ASSERT(type == kCoonsPatchMeshShading || + type == kTensorProductPatchMeshShading); CFX_FxgeDevice device; device.Attach(pBitmap, false, nullptr, false); - CPDF_MeshStream stream(funcs, pCS); - if (!stream.Load(pShadingStream)) - return; - if (!CheckCoonTensorPara(stream)) + CPDF_MeshStream stream(type, funcs, pShadingStream, pCS); + if (!stream.Load()) return; CPDF_PatchDrawer patch; @@ -766,11 +752,10 @@ void DrawCoonPatchMeshes( patch.path.SetPointCount(13); FX_PATHPOINT* pPoints = patch.path.GetPoints(); pPoints[0].m_Flag = FXPT_MOVETO; - for (int i = 1; i < 13; i++) { + for (int i = 1; i < 13; i++) pPoints[i].m_Flag = FXPT_BEZIERTO; - } CFX_PointF coords[16]; - int point_count = bTensor ? 16 : 12; + int point_count = type == kTensorProductPatchMeshShading ? 16 : 12; while (!stream.BitStream()->IsEOF()) { uint32_t flag = stream.GetFlag(); int iStartPoint = 0, iStartColor = 0, i = 0; @@ -934,10 +919,8 @@ void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, // The shading object can be a stream or a dictionary. We do not handle // the case of dictionary at the moment. if (CPDF_Stream* pStream = ToStream(pPattern->GetShadingObject())) { - DrawCoonPatchMeshes( - pPattern->GetShadingType() == kTensorProductPatchMeshShading, - pBitmap, &FinalMatrix, pStream, funcs, pColorSpace, fill_mode, - alpha); + DrawCoonPatchMeshes(pPattern->GetShadingType(), pBitmap, &FinalMatrix, + pStream, funcs, pColorSpace, fill_mode, alpha); } } break; } -- cgit v1.2.3