Merge to XFA: Fix infinite recursion in CPDF_RenderStatus::RenderSingleObject().
authorTom Sepez <tsepez@chromium.org>
Fri, 30 Jan 2015 02:16:16 +0000 (18:16 -0800)
committerTom Sepez <tsepez@chromium.org>
Fri, 30 Jan 2015 02:16:16 +0000 (18:16 -0800)
This brings in:
14b2bb0 Fix infinite recursion in CPDF_RenderStatus::RenderSingleObject().
1d43e82 Add minimized test cases for stack exhaustion crash to repository.

TBR=thestig@chromium.org

Review URL: https://codereview.chromium.org/893493002

core/src/fpdfapi/fpdf_render/fpdf_render.cpp
core/src/fpdfapi/fpdf_render/fpdf_render_image.cpp
core/src/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp
core/src/fpdfapi/fpdf_render/render_int.h
testing/resources/bug_451265.in [new file with mode: 0644]
testing/resources/bug_451265.pdf [new file with mode: 0644]

index ab1ddb6..490ceb9 100644 (file)
@@ -180,11 +180,14 @@ FX_ARGB CPDF_RenderOptions::TranslateColor(FX_ARGB argb) const
     b = (bb - fb) * gray / 255 + fb;
     return ArgbEncode(a, r, g, b);
 }
+
+// static
+int CPDF_RenderStatus::s_CurrentRecursionDepth = 0;
+
 CPDF_RenderStatus::CPDF_RenderStatus()
 {
     m_pContext = NULL;
     m_bStopped = FALSE;
-    m_Level = 0;
     m_pDevice = NULL;
     m_pCurObj = NULL;
     m_pStopObj = NULL;
@@ -203,13 +206,15 @@ CPDF_RenderStatus::CPDF_RenderStatus()
     m_pPageResource = NULL;
     m_curBlend = FXDIB_BLEND_NORMAL;
 }
+
 CPDF_RenderStatus::~CPDF_RenderStatus()
 {
     if (m_pObjectRenderer) {
         delete m_pObjectRenderer;
     }
 }
-FX_BOOL CPDF_RenderStatus::Initialize(int level, CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice,
+
+FX_BOOL CPDF_RenderStatus::Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice,
                                       const CFX_AffineMatrix* pDeviceMatrix, const CPDF_PageObject* pStopObj,
                                       const CPDF_RenderStatus* pParentState, const CPDF_GraphicStates* pInitialStates,
                                       const CPDF_RenderOptions* pOptions, int transparency, FX_BOOL bDropObjects,
@@ -217,7 +222,6 @@ FX_BOOL CPDF_RenderStatus::Initialize(int level, CPDF_RenderContext* pContext, C
                                       FX_ARGB fill_color, FX_DWORD GroupFamily,
                                       FX_BOOL bLoadMask)
 {
-    m_Level = level;
     m_pContext = pContext;
     m_pDevice = pDevice;
     m_DitherBits = pDevice->GetDeviceCaps(FXDC_DITHER_BITS);
@@ -262,9 +266,6 @@ FX_BOOL CPDF_RenderStatus::Initialize(int level, CPDF_RenderContext* pContext, C
 }
 void CPDF_RenderStatus::RenderObjectList(const CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObj2Device)
 {
-    if (m_Level > 32) {
-        return;
-    }
     CFX_FloatRect clip_rect = m_pDevice->GetClipBox();
     CFX_AffineMatrix device2object;
     device2object.SetReverse(*pObj2Device);
@@ -293,14 +294,16 @@ void CPDF_RenderStatus::RenderObjectList(const CPDF_PageObjects* pObjs, const CF
 }
 void CPDF_RenderStatus::RenderSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
 {
-    if (m_Level > 32) {
+    CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
+    if (++s_CurrentRecursionDepth > kRenderMaxRecursionDepth) {
         return;
     }
     m_pCurObj = pObj;
-    if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull())
+    if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull()) {
         if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
             return;
         }
+    }
     ProcessClipPath(pObj->m_ClipPath, pObj2Device);
     if (ProcessTransparency(pObj, pObj2Device)) {
         return;
@@ -462,7 +465,7 @@ void CPDF_RenderStatus::DrawObjWithBackground(const CPDF_PageObject* pObj, const
         }
     }
     CPDF_RenderStatus status;
-    status.Initialize(m_Level + 1, m_pContext, buffer.GetDevice(), buffer.GetMatrix(), NULL, NULL, NULL, &m_Options, m_Transparency, m_bDropObjects, pFormResource);
+    status.Initialize(m_pContext, buffer.GetDevice(), buffer.GetMatrix(), NULL, NULL, NULL, &m_Options, m_Transparency, m_bDropObjects, pFormResource);
     status.RenderSingleObject(pObj, &matrix);
     buffer.OutputToDevice();
 }
@@ -479,7 +482,7 @@ FX_BOOL CPDF_RenderStatus::ProcessForm(CPDF_FormObject* pFormObj, const CFX_Affi
         pResources = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
     }
     CPDF_RenderStatus status;
-    status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, m_pStopObj,
+    status.Initialize(m_pContext, m_pDevice, NULL, m_pStopObj,
                       this, pFormObj, &m_Options, m_Transparency, m_bDropObjects, pResources, FALSE);
     status.m_curBlend = m_curBlend;
     m_pDevice->SaveState();
@@ -837,7 +840,7 @@ FX_BOOL CPDF_RenderStatus::ProcessTransparency(const CPDF_PageObject* pPageObj,
         }
     }
     CPDF_RenderStatus bitmap_render;
-    bitmap_render.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL,
+    bitmap_render.Initialize(m_pContext, &bitmap_device, NULL,
                              m_pStopObj, NULL, NULL, &m_Options, 0, m_bDropObjects, pFormResource, TRUE);
     bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
     m_bStopped = bitmap_render.m_bStopped;
@@ -1001,7 +1004,7 @@ void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_PageObject
             CFX_AffineMatrix FinalMatrix = pItem->m_Matrix;
             FinalMatrix.Concat(*pLastMatrix);
             CPDF_RenderStatus status;
-            status.Initialize(0, this, pDevice, pLastMatrix, pStopObj, NULL, NULL, pOptions,
+            status.Initialize(this, pDevice, pLastMatrix, pStopObj, NULL, NULL, pOptions,
                               pItem->m_pObjectList->m_Transparency, FALSE, NULL);
             status.RenderObjectList(pItem->m_pObjectList, &FinalMatrix);
             if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
@@ -1013,7 +1016,7 @@ void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_PageObject
             }
         } else {
             CPDF_RenderStatus status;
-            status.Initialize(0, this, pDevice, NULL, pStopObj, NULL, NULL, pOptions,
+            status.Initialize(this, pDevice, NULL, pStopObj, NULL, NULL, pOptions,
                               pItem->m_pObjectList->m_Transparency, FALSE, NULL);
             status.RenderObjectList(pItem->m_pObjectList, &pItem->m_Matrix);
             if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
@@ -1117,7 +1120,7 @@ void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause)
             m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition();
             m_ObjectIndex = 0;
             m_pRenderer = FX_NEW CPDF_RenderStatus();
-            m_pRenderer->Initialize(0, m_pContext, m_pDevice, NULL, NULL, NULL, NULL,
+            m_pRenderer->Initialize(m_pContext, m_pDevice, NULL, NULL, NULL, NULL,
                                     m_pOptions, pItem->m_pObjectList->m_Transparency, m_bDropObjects, NULL);
             m_pDevice->SaveState();
             m_ClipRect = m_pDevice->GetClipBox();
index ffe559a..02da1d9 100644 (file)
@@ -489,7 +489,7 @@ FX_BOOL     CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device)
     bitmap_device1.GetBitmap()->Clear(0xffffff);
     {
         CPDF_RenderStatus bitmap_render;
-        bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device1, NULL, NULL,
+        bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, NULL, NULL,
                                  NULL, NULL, &m_pRenderStatus->m_Options, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE);
         CFX_Matrix patternDevice = *pObj2Device;
         patternDevice.Translate((FX_FLOAT) - rect.left, (FX_FLOAT) - rect.top);
@@ -506,7 +506,7 @@ FX_BOOL     CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device)
         }
         bitmap_device2.GetBitmap()->Clear(0);
         CPDF_RenderStatus bitmap_render;
-        bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device2, NULL, NULL,
+        bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, NULL, NULL,
                                  NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE);
         CPDF_ImageRenderer image_render;
         if (image_render.Start(&bitmap_render, m_pDIBSource, 0xffffffff, 255, &new_matrix, m_Flags, TRUE)) {
@@ -579,7 +579,7 @@ FX_BOOL CPDF_ImageRenderer::DrawMaskedImage()
     bitmap_device1.GetBitmap()->Clear(0xffffff);
     {
         CPDF_RenderStatus bitmap_render;
-        bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device1, NULL, NULL,
+        bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, NULL, NULL,
                                  NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE);
         CPDF_ImageRenderer image_render;
         if (image_render.Start(&bitmap_render, m_pDIBSource, 0, 255, &new_matrix, m_Flags, TRUE)) {
@@ -593,7 +593,7 @@ FX_BOOL CPDF_ImageRenderer::DrawMaskedImage()
         }
         bitmap_device2.GetBitmap()->Clear(0);
         CPDF_RenderStatus bitmap_render;
-        bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device2, NULL, NULL,
+        bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, NULL, NULL,
                                  NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE);
         CPDF_ImageRenderer image_render;
         if (image_render.Start(&bitmap_render, m_Loader.m_pMask, 0xffffffff, 255, &new_matrix, m_Flags, TRUE)) {
@@ -1034,7 +1034,7 @@ CFX_DIBitmap* CPDF_RenderStatus::LoadSMask(CPDF_Dictionary* pSMaskDict,
     CPDF_RenderOptions options;
     options.m_ColorMode = bLuminosity ? RENDER_COLOR_NORMAL : RENDER_COLOR_ALPHA;
     CPDF_RenderStatus status;
-    status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, NULL, NULL,
+    status.Initialize(m_pContext, &bitmap_device, NULL, NULL, NULL, NULL,
                       &options, 0, m_bDropObjects, pFormResource, TRUE, NULL, 0, pCS ? pCS->GetFamily() : 0, bLuminosity);
     status.RenderObjectList(&form, &matrix);
     pMask = FX_NEW CFX_DIBitmap;
index 6b895b5..8024c99 100644 (file)
@@ -988,7 +988,7 @@ void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern, CPDF_Pag
                 matrix.Translate(orig_x - mtPattern2Device.e, orig_y - mtPattern2Device.f);
                 m_pDevice->SaveState();
                 CPDF_RenderStatus status;
-                status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, NULL, this, pStates, &m_Options,
+                status.Initialize(m_pContext, m_pDevice, NULL, NULL, this, pStates, &m_Options,
                                   pPattern->m_pForm->m_Transparency, m_bDropObjects, pFormResource);
                 status.RenderObjectList(pPattern->m_pForm, &matrix);
                 m_pDevice->RestoreState();
index 449b003..f99f7ce 100644 (file)
@@ -423,7 +423,7 @@ FX_BOOL CPDF_RenderStatus::ProcessType3Text(const CPDF_TextObject* textobj, cons
             }
             if (fill_alpha == 255) {
                 CPDF_RenderStatus status;
-                status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, NULL, this, pStates, &Options,
+                status.Initialize(m_pContext, m_pDevice, NULL, NULL, this, pStates, &Options,
                                   pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb);
                 status.m_Type3FontCache.Append(m_Type3FontCache);
                 status.m_Type3FontCache.Add(pType3Font);
@@ -440,7 +440,7 @@ FX_BOOL CPDF_RenderStatus::ProcessType3Text(const CPDF_TextObject* textobj, cons
                 }
                 bitmap_device.GetBitmap()->Clear(0);
                 CPDF_RenderStatus status;
-                status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, this, pStates, &Options,
+                status.Initialize(m_pContext, &bitmap_device, NULL, NULL, this, pStates, &Options,
                                   pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb);
                 status.m_Type3FontCache.Append(m_Type3FontCache);
                 status.m_Type3FontCache.Add(pType3Font);
index 81feb5e..bd7d375 100644 (file)
@@ -92,7 +92,7 @@ class CPDF_RenderStatus : public CFX_Object
 public:
     CPDF_RenderStatus();
     ~CPDF_RenderStatus();
-    FX_BOOL                    Initialize(int level, class CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, const CFX_AffineMatrix* pDeviceMatrix,
+    FX_BOOL                    Initialize(class CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, const CFX_AffineMatrix* pDeviceMatrix,
                                const CPDF_PageObject* pStopObj, const CPDF_RenderStatus* pParentStatus,
                                const CPDF_GraphicStates* pInitialStates, const CPDF_RenderOptions* pOptions,
                                int transparency, FX_BOOL bDropObjects, CPDF_Dictionary* pFormResource = NULL,
@@ -155,8 +155,11 @@ protected:
     void                       DitherObjectArea(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device);
     FX_BOOL                    GetObjectClippedRect(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bLogical, FX_RECT &rect) const;
     void                       GetScaledMatrix(CFX_Matrix &matrix) const;
+
 protected:
-    int                                                m_Level;
+    static const int kRenderMaxRecursionDepth = 64;
+    static int s_CurrentRecursionDepth;
+
     CFX_RenderDevice*          m_pDevice;
     CFX_AffineMatrix           m_DeviceMatrix;
     CPDF_ClipPath                      m_LastClipPath;
diff --git a/testing/resources/bug_451265.in b/testing/resources/bug_451265.in
new file mode 100644 (file)
index 0000000..7fb2764
--- /dev/null
@@ -0,0 +1,80 @@
+{{header}}
+{{object 1 0}} <<
+  /Kids [3 0 R]
+  /Type /Pages
+  /Count 1
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Catalog
+  /Pages 1 0 R
+>>
+endobj
+{{object 3 0}} <<
+  /Resources 11 0 R
+  /Type /Page
+  /Contents 10 0 R
+  /Parent 1 0 R
+>>
+endobj
+{{object 10 0}} <<
+>>
+stream
+1 0 0 1 315.779 733.039 cm
+1 0 0 1 2.835 -173.614 cm
+1.04704 0 0 1.04704 0 0 cm
+/Im6 Do
+endstream
+endobj
+{{object 11 0}} <<
+  /XObject <<
+    /Im6 12 0 R
+  >>
+>>
+endobj
+{{object 12 0}} <<
+  /Subtype /Form
+  /Resources <<
+    /XObject <<
+      /x15 13 0 R
+    >>
+  >>
+>>
+stream
+/x15 Do
+endstream
+endobj
+{{object 13 0}} <<
+  /Subtype /Form
+  /Resources <<
+    /Pattern <<
+      /p31 14 0 R
+    >>
+  >>
+>>
+stream
+q /Pattern cs /p31 scn /a0 gs
+0 0 224.720001 160.399994 re f
+Q
+endstream
+endobj
+{{object 14 0}} <<
+  /PatternType 1
+  /BBox [0 0 225 161]
+  /Resources <<
+    /XObject <<
+      /x47 12 0 R
+    >>
+  >>
+>>
+stream
+/x47 Do
+endstream
+endobj
+{{xref}}
+trailer <<
+  /Root 2 0 R
+  /Size 110
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_451265.pdf b/testing/resources/bug_451265.pdf
new file mode 100644 (file)
index 0000000..299363d
--- /dev/null
@@ -0,0 +1,98 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Kids [3 0 R]
+  /Type /Pages
+  /Count 1
+>>
+endobj
+2 0 obj <<
+  /Type /Catalog
+  /Pages 1 0 R
+>>
+endobj
+3 0 obj <<
+  /Resources 11 0 R
+  /Type /Page
+  /Contents 10 0 R
+  /Parent 1 0 R
+>>
+endobj
+10 0 obj <<
+>>
+stream
+1 0 0 1 315.779 733.039 cm
+1 0 0 1 2.835 -173.614 cm
+1.04704 0 0 1.04704 0 0 cm
+/Im6 Do
+endstream
+endobj
+11 0 obj <<
+  /XObject <<
+    /Im6 12 0 R
+  >>
+>>
+endobj
+12 0 obj <<
+  /Subtype /Form
+  /Resources <<
+    /XObject <<
+      /x15 13 0 R
+    >>
+  >>
+>>
+stream
+/x15 Do
+endstream
+endobj
+13 0 obj <<
+  /Subtype /Form
+  /Resources <<
+    /Pattern <<
+      /p31 14 0 R
+    >>
+  >>
+>>
+stream
+q /Pattern cs /p31 scn /a0 gs
+0 0 224.720001 160.399994 re f
+Q
+endstream
+endobj
+14 0 obj <<
+  /PatternType 1
+  /BBox [0 0 225 161]
+  /Resources <<
+    /XObject <<
+      /x47 12 0 R
+    >>
+  >>
+>>
+stream
+/x47 Do
+endstream
+endobj
+xref
+0 15
+0000000000 65536 f
+0000000015 00000 n
+0000000078 00000 n
+0000000131 00000 n
+0000000000 65536 f
+0000000000 65536 f
+0000000000 65536 f
+0000000000 65536 f
+0000000000 65536 f
+0000000000 65536 f
+0000000221 00000 n
+0000000348 00000 n
+0000000405 00000 n
+0000000531 00000 n
+0000000712 00000 n
+trailer <<
+  /Root 2 0 R
+  /Size 110
+>>
+startxref
+860
+%%EOF