From 430ab8363e77c48b2c2435af4d289f85e2be1b96 Mon Sep 17 00:00:00 2001 From: tsepez Date: Fri, 18 Nov 2016 14:48:21 -0800 Subject: Add unit test for CXFA_FileRead. The FileRead's return convention is being modified at https://codereview.chromium.org/2430743003/, so first provide a test of the old behaviour. Fix some issues with null dictionaries as provided by the CPDF_Stream default ctor along the way. Review-Url: https://codereview.chromium.org/2517513003 --- BUILD.gn | 1 + core/fpdfapi/edit/fpdf_edit_create.cpp | 34 ++++++------- core/fpdfapi/parser/cpdf_stream.cpp | 4 ++ core/fpdfapi/parser/cpdf_stream.h | 1 + core/fpdfapi/parser/cpdf_stream_acc.cpp | 20 +++----- xfa/fxfa/app/xfa_ffapp_unittest.cpp | 86 +++++++++++++++++++++++++++++++++ 6 files changed, 116 insertions(+), 30 deletions(-) create mode 100644 xfa/fxfa/app/xfa_ffapp_unittest.cpp diff --git a/BUILD.gn b/BUILD.gn index 8c520182b8..be9ced7cee 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1743,6 +1743,7 @@ test("pdfium_unittests") { "xfa/fde/css/fde_cssdatatable_unittest.cpp", "xfa/fde/xml/fde_xml_imp_unittest.cpp", "xfa/fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp", + "xfa/fxfa/app/xfa_ffapp_unittest.cpp", "xfa/fxfa/app/xfa_textlayout_unittest.cpp", "xfa/fxfa/fm2js/xfa_simpleexpression_unittest.cpp", "xfa/fxfa/parser/xfa_utils_unittest.cpp", diff --git a/core/fpdfapi/edit/fpdf_edit_create.cpp b/core/fpdfapi/edit/fpdf_edit_create.cpp index ff12606399..360472948d 100644 --- a/core/fpdfapi/edit/fpdf_edit_create.cpp +++ b/core/fpdfapi/edit/fpdf_edit_create.cpp @@ -417,26 +417,24 @@ CPDF_FlateEncoder::CPDF_FlateEncoder(CPDF_Stream* pStream, bool bFlateEncode) m_bCloned(false), m_bNewData(false) { m_Acc.LoadAllData(pStream, true); - if ((pStream && pStream->GetDict() && - pStream->GetDict()->KeyExist("Filter")) || - !bFlateEncode) { - if (pStream->GetDict()->KeyExist("Filter") && !bFlateEncode) { - CPDF_StreamAcc destAcc; - destAcc.LoadAllData(pStream); - m_dwSize = destAcc.GetSize(); - m_pData = (uint8_t*)destAcc.DetachData(); - m_pDict = ToDictionary(pStream->GetDict()->Clone().release()); - m_pDict->RemoveFor("Filter"); - m_bNewData = true; - m_bCloned = true; - } else { - m_pData = (uint8_t*)m_Acc.GetData(); - m_dwSize = m_Acc.GetSize(); - m_pDict = pStream->GetDict(); - } + bool bHasFilter = pStream && pStream->HasFilter(); + if (bHasFilter && !bFlateEncode) { + CPDF_StreamAcc destAcc; + destAcc.LoadAllData(pStream); + m_dwSize = destAcc.GetSize(); + m_pData = (uint8_t*)destAcc.DetachData(); + m_pDict = ToDictionary(pStream->GetDict()->Clone().release()); + m_pDict->RemoveFor("Filter"); + m_bNewData = true; + m_bCloned = true; + return; + } + if (bHasFilter || !bFlateEncode) { + m_pData = (uint8_t*)m_Acc.GetData(); + m_dwSize = m_Acc.GetSize(); + m_pDict = pStream->GetDict(); return; } - m_bNewData = true; m_bCloned = true; // TODO(thestig): Move to Init() and check return value. diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp index e8ee022940..64261b14d3 100644 --- a/core/fpdfapi/parser/cpdf_stream.cpp +++ b/core/fpdfapi/parser/cpdf_stream.cpp @@ -113,6 +113,10 @@ bool CPDF_Stream::ReadRawData(FX_FILESIZE offset, return true; } +bool CPDF_Stream::HasFilter() const { + return m_pDict && m_pDict->KeyExist("Filter"); +} + CFX_WideString CPDF_Stream::GetUnicodeText() const { CPDF_StreamAcc stream; stream.LoadAllData(this, false); diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h index ddf7cc5b69..c4f9aacf2b 100644 --- a/core/fpdfapi/parser/cpdf_stream.h +++ b/core/fpdfapi/parser/cpdf_stream.h @@ -46,6 +46,7 @@ class CPDF_Stream : public CPDF_Object { uint32_t buf_size) const; bool IsMemoryBased() const { return m_bMemoryBased; } + bool HasFilter() const; protected: std::unique_ptr CloneNonCyclic( diff --git a/core/fpdfapi/parser/cpdf_stream_acc.cpp b/core/fpdfapi/parser/cpdf_stream_acc.cpp index 81439bc677..01d8e148df 100644 --- a/core/fpdfapi/parser/cpdf_stream_acc.cpp +++ b/core/fpdfapi/parser/cpdf_stream_acc.cpp @@ -24,17 +24,16 @@ void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream, return; m_pStream = pStream; - if (pStream->IsMemoryBased() && - (!pStream->GetDict()->KeyExist("Filter") || bRawAccess)) { + if (pStream->IsMemoryBased() && (!pStream->HasFilter() || bRawAccess)) { m_dwSize = pStream->GetRawSize(); m_pData = pStream->GetRawData(); return; } - uint8_t* pSrcData; uint32_t dwSrcSize = pStream->GetRawSize(); if (dwSrcSize == 0) return; + uint8_t* pSrcData; if (!pStream->IsMemoryBased()) { pSrcData = m_pSrcData = FX_Alloc(uint8_t, dwSrcSize); if (!pStream->ReadRawData(0, pSrcData, dwSrcSize)) @@ -42,17 +41,14 @@ void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream, } else { pSrcData = pStream->GetRawData(); } - if (!pStream->GetDict()->KeyExist("Filter") || bRawAccess) { + if (!pStream->HasFilter() || bRawAccess) { + m_pData = pSrcData; + m_dwSize = dwSrcSize; + } else if (!PDF_DataDecode(pSrcData, dwSrcSize, m_pStream->GetDict(), m_pData, + m_dwSize, m_ImageDecoder, m_pImageParam, + estimated_size, bImageAcc)) { m_pData = pSrcData; m_dwSize = dwSrcSize; - } else { - bool bRet = PDF_DataDecode(pSrcData, dwSrcSize, m_pStream->GetDict(), - m_pData, m_dwSize, m_ImageDecoder, m_pImageParam, - estimated_size, bImageAcc); - if (!bRet) { - m_pData = pSrcData; - m_dwSize = dwSrcSize; - } } if (pSrcData != pStream->GetRawData() && pSrcData != m_pData) FX_Free(pSrcData); diff --git a/xfa/fxfa/app/xfa_ffapp_unittest.cpp b/xfa/fxfa/app/xfa_ffapp_unittest.cpp new file mode 100644 index 0000000000..7e1b9d7237 --- /dev/null +++ b/xfa/fxfa/app/xfa_ffapp_unittest.cpp @@ -0,0 +1,86 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "xfa/fxfa/xfa_ffapp.h" + +#include + +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fxcrt/fx_memory.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/ptr_util.h" + +using UniqueFileRead = + std::unique_ptr>; + +TEST(CXFAFileRead, NoStreams) { + std::vector streams; + UniqueFileRead fileread(new CXFA_FileRead(streams)); + + uint8_t output_buffer[16]; + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_FALSE(fileread->ReadBlock(output_buffer, 0, 0)); + EXPECT_EQ(0xbd, output_buffer[0]); +} + +TEST(CXFAFileRead, EmptyStreams) { + std::vector streams; + std::unique_ptr stream1 = pdfium::MakeUnique(); + streams.push_back(stream1.get()); + UniqueFileRead fileread(new CXFA_FileRead(streams)); + + uint8_t output_buffer[16]; + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_FALSE(fileread->ReadBlock(output_buffer, 0, 0)); + EXPECT_EQ(0xbd, output_buffer[0]); +} + +TEST(CXFAFileRead, NormalStreams) { + std::vector streams; + std::unique_ptr stream1 = pdfium::MakeUnique(); + std::unique_ptr stream2 = pdfium::MakeUnique(); + std::unique_ptr stream3 = pdfium::MakeUnique(); + + // 16 chars total. + stream1->InitStream(reinterpret_cast("one t"), 5, + new CPDF_Dictionary()); + stream2->InitStream(reinterpret_cast("wo "), 3, + new CPDF_Dictionary()); + stream3->InitStream(reinterpret_cast("three!!!"), 8, + new CPDF_Dictionary()); + + streams.push_back(stream1.get()); + streams.push_back(stream2.get()); + streams.push_back(stream3.get()); + UniqueFileRead fileread(new CXFA_FileRead(streams)); + + uint8_t output_buffer[16]; + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_TRUE(fileread->ReadBlock(output_buffer, 0, 0)); + EXPECT_EQ(0xbd, output_buffer[0]); + + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_TRUE(fileread->ReadBlock(output_buffer, 1, 0)); + EXPECT_EQ(0xbd, output_buffer[0]); + + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_TRUE(fileread->ReadBlock(output_buffer, 0, 1)); + EXPECT_EQ(0, memcmp(output_buffer, "o", 1)); + EXPECT_EQ(0xbd, output_buffer[1]); + + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_TRUE(fileread->ReadBlock(output_buffer, 0, sizeof(output_buffer))); + EXPECT_EQ(0, memcmp(output_buffer, "one two three!!!", 16)); + + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_TRUE(fileread->ReadBlock(output_buffer, 2, 10)); + EXPECT_EQ(0, memcmp(output_buffer, "e two thre", 10)); + EXPECT_EQ(0xbd, output_buffer[11]); + + memset(output_buffer, 0xbd, sizeof(output_buffer)); + EXPECT_FALSE(fileread->ReadBlock(output_buffer, 1, sizeof(output_buffer))); + EXPECT_EQ(0, memcmp(output_buffer, "ne two three!!!", 15)); + EXPECT_EQ(0xbd, output_buffer[15]); +} -- cgit v1.2.3