From 5b590337e0778b49dd7092af4a283ed0f9c5a2e9 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Wed, 10 May 2017 13:59:14 -0400 Subject: Store the offset in the archive buffer This Cl moves the implementation of the archive buffer behind an IFX_ArchiveStream interface. The buffer holds the current offset and the offset parameter is removed from the CPDF_Creator and various other methods. Change-Id: Ia54e803b58bbfb6ef03fec4a940d2c056d541356 Reviewed-on: https://pdfium-review.googlesource.com/5255 Reviewed-by: Tom Sepez Commit-Queue: dsinclair --- core/fpdfapi/edit/cpdf_creator.cpp | 399 ++++++++++++++++---------------- core/fpdfapi/edit/cpdf_creator.h | 9 +- core/fpdfapi/edit/cpdf_objectstream.cpp | 56 ++--- core/fpdfapi/edit/cpdf_xrefstream.cpp | 202 +++++----------- 4 files changed, 283 insertions(+), 383 deletions(-) (limited to 'core/fpdfapi/edit') diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp index 0aa9fb0b1b..e782de3dbc 100644 --- a/core/fpdfapi/edit/cpdf_creator.cpp +++ b/core/fpdfapi/edit/cpdf_creator.cpp @@ -6,6 +6,8 @@ #include "core/fpdfapi/edit/cpdf_creator.h" +#include + #include "core/fpdfapi/edit/cpdf_encryptor.h" #include "core/fpdfapi/edit/cpdf_flateencoder.h" #include "core/fpdfapi/edit/cpdf_objectstream.h" @@ -23,6 +25,91 @@ namespace { const uint32_t kXRefStreamMaxSize = 10000; +const size_t kArchiveBufferSize = 32768; + +class CFX_FileBufferArchive : public IFX_ArchiveStream { + public: + explicit CFX_FileBufferArchive(const CFX_RetainPtr& archive); + ~CFX_FileBufferArchive() override; + + bool WriteBlock(const void* pBuf, size_t size) override; + bool WriteByte(uint8_t byte) override; + bool WriteDWord(uint32_t i) override; + bool WriteString(const CFX_ByteStringC& str) override; + + FX_FILESIZE CurrentOffset() const override { return offset_; } + + private: + bool Flush(); + + FX_FILESIZE offset_; + size_t current_length_; + std::vector buffer_; + CFX_RetainPtr backing_file_; +}; + +CFX_FileBufferArchive::CFX_FileBufferArchive( + const CFX_RetainPtr& file) + : offset_(0), + current_length_(0), + buffer_(kArchiveBufferSize), + backing_file_(file) { + ASSERT(file); +} + +CFX_FileBufferArchive::~CFX_FileBufferArchive() { + Flush(); +} + +bool CFX_FileBufferArchive::Flush() { + size_t nRemaining = current_length_; + current_length_ = 0; + if (!backing_file_) + return false; + if (!nRemaining) + return true; + return backing_file_->WriteBlock(buffer_.data(), nRemaining); +} + +bool CFX_FileBufferArchive::WriteBlock(const void* pBuf, size_t size) { + ASSERT(pBuf && size > 0); + + const uint8_t* buffer = reinterpret_cast(pBuf); + size_t temp_size = size; + while (temp_size) { + size_t buf_size = std::min(kArchiveBufferSize - current_length_, temp_size); + memcpy(buffer_.data() + current_length_, buffer, buf_size); + + current_length_ += buf_size; + if (current_length_ == kArchiveBufferSize && !Flush()) + return false; + + temp_size -= buf_size; + buffer += buf_size; + } + + pdfium::base::CheckedNumeric safe_offset = offset_; + safe_offset += size; + if (!safe_offset.IsValid()) + return false; + + offset_ = safe_offset.ValueOrDie(); + return true; +} + +bool CFX_FileBufferArchive::WriteByte(uint8_t byte) { + return WriteBlock(&byte, 1); +} + +bool CFX_FileBufferArchive::WriteDWord(uint32_t i) { + char buf[32]; + FXSYS_itoa(i, buf, 10); + return WriteBlock(buf, static_cast(FXSYS_strlen(buf))); +} + +bool CFX_FileBufferArchive::WriteString(const CFX_ByteStringC& str) { + return WriteBlock(str.raw_str(), str.GetLength()); +} std::vector GenerateFileID(uint32_t dwSeed1, uint32_t dwSeed2) { std::vector buffer(sizeof(uint32_t) * 4); @@ -40,12 +127,12 @@ std::vector GenerateFileID(uint32_t dwSeed1, uint32_t dwSeed2) { return buffer; } -int32_t OutputIndex(CFX_FileBufferArchive* pFile, FX_FILESIZE offset) { - if (pFile->AppendByte(static_cast(offset >> 24)) < 0 || - pFile->AppendByte(static_cast(offset >> 16)) < 0 || - pFile->AppendByte(static_cast(offset >> 8)) < 0 || - pFile->AppendByte(static_cast(offset)) < 0 || - pFile->AppendByte(0) < 0) { +int32_t OutputIndex(IFX_ArchiveStream* archive, FX_FILESIZE offset) { + if (!archive->WriteByte(static_cast(offset >> 24)) || + !archive->WriteByte(static_cast(offset >> 16)) || + !archive->WriteByte(static_cast(offset >> 8)) || + !archive->WriteByte(static_cast(offset)) || + !archive->WriteByte(0)) { return -1; } return 0; @@ -54,7 +141,7 @@ int32_t OutputIndex(CFX_FileBufferArchive* pFile, FX_FILESIZE offset) { } // namespace CPDF_Creator::CPDF_Creator(CPDF_Document* pDoc, - const CFX_RetainPtr& pFile) + const CFX_RetainPtr& archive) : m_pDocument(pDoc), m_pParser(pDoc->GetParser()), m_bSecurityChanged(false), @@ -63,20 +150,16 @@ CPDF_Creator::CPDF_Creator(CPDF_Document* pDoc, m_pCryptoHandler(m_pParser ? m_pParser->GetCryptoHandler() : nullptr), m_pMetadata(nullptr), m_dwLastObjNum(m_pDocument->GetLastObjNum()), - m_Offset(0), + m_Archive(pdfium::MakeUnique(archive)), m_SavedOffset(0), m_iStage(-1), m_dwFlags(0), m_CurObjNum(0), m_XrefStart(0), m_pIDArray(nullptr), - m_FileVersion(0) { - m_File.AttachFile(pFile); -} + m_FileVersion(0) {} -CPDF_Creator::~CPDF_Creator() { - Clear(); -} +CPDF_Creator::~CPDF_Creator() {} bool CPDF_Creator::IsXRefNeedEnd() { if (!IsIncremental()) @@ -125,36 +208,19 @@ bool CPDF_Creator::WriteStream(const CPDF_Object* pStream, encoder.GetDict()->SetNewFor( "Length", static_cast(encryptor.GetSize())); } - if (!WriteDirectObj(objnum, encoder.GetDict(), true)) - return false; - - int len = m_File.AppendString("stream\r\n"); - if (len < 0) - return false; - m_Offset += len; - - if (m_File.AppendBlock(encryptor.GetData(), encryptor.GetSize()) < 0) + if (!WriteDirectObj(objnum, encoder.GetDict(), true) || + !m_Archive->WriteString("stream\r\n") || + !m_Archive->WriteBlock(encryptor.GetData(), encryptor.GetSize()) || + !m_Archive->WriteString("\r\nendstream")) { return false; - m_Offset += encryptor.GetSize(); - - len = m_File.AppendString("\r\nendstream"); - if (len < 0) - return false; - m_Offset += len; + } return true; } bool CPDF_Creator::WriteIndirectObj(uint32_t objnum, const CPDF_Object* pObj) { - int32_t len = m_File.AppendDWord(objnum); - if (len < 0) - return false; - m_Offset += len; - - len = m_File.AppendString(" 0 obj\r\n"); - if (len < 0) + if (!m_Archive->WriteDWord(objnum) || !m_Archive->WriteString(" 0 obj\r\n")) return false; - m_Offset += len; if (pObj->IsStream()) { CPDF_CryptoHandler* pHandler = @@ -165,13 +231,10 @@ bool CPDF_Creator::WriteIndirectObj(uint32_t objnum, const CPDF_Object* pObj) { return false; } - len = m_File.AppendString("\r\nendobj\r\n"); - if (len < 0) - return false; - - m_Offset += len; - if (!AppendObjectNumberToXRef(objnum)) + if (!m_Archive->WriteString("\r\nendobj\r\n") || + !AppendObjectNumberToXRef(objnum)) { return false; + } return true; } @@ -214,7 +277,7 @@ bool CPDF_Creator::WriteDirectObj(uint32_t objnum, case CPDF_Object::NULLOBJ: case CPDF_Object::NUMBER: case CPDF_Object::REFERENCE: - if (!pObj->WriteTo(&m_File, &m_Offset)) + if (!pObj->WriteTo(m_Archive.get())) return false; break; @@ -222,7 +285,7 @@ bool CPDF_Creator::WriteDirectObj(uint32_t objnum, CFX_ByteString str = pObj->GetString(); bool bHex = pObj->AsString()->IsHex(); if (!m_pCryptoHandler || !bEncrypt) { - if (!pObj->WriteTo(&m_File, &m_Offset)) + if (!pObj->WriteTo(m_Archive.get())) return false; break; } @@ -230,11 +293,8 @@ bool CPDF_Creator::WriteDirectObj(uint32_t objnum, (uint8_t*)str.c_str(), str.GetLength()); CFX_ByteString content = PDF_EncodeString( CFX_ByteString(encryptor.GetData(), encryptor.GetSize()), bHex); - int32_t len = m_File.AppendString(content.AsStringC()); - if (len < 0) + if (!m_Archive->WriteString(content.AsStringC())) return false; - - m_Offset += len; break; } case CPDF_Object::STREAM: { @@ -248,94 +308,71 @@ bool CPDF_Creator::WriteDirectObj(uint32_t objnum, encoder.GetDict()->SetNewFor( "Length", static_cast(encryptor.GetSize())); } - if (!WriteDirectObj(objnum, encoder.GetDict(), true)) + if (!WriteDirectObj(objnum, encoder.GetDict(), true) || + !m_Archive->WriteString("stream\r\n") || + !m_Archive->WriteBlock(encryptor.GetData(), encryptor.GetSize()) || + !m_Archive->WriteString("\r\nendstream")) { return false; - - int32_t len = m_File.AppendString("stream\r\n"); - if (len < 0) - return false; - m_Offset += len; - - if (m_File.AppendBlock(encryptor.GetData(), encryptor.GetSize()) < 0) - return false; - m_Offset += encryptor.GetSize(); - - len = m_File.AppendString("\r\nendstream"); - if (len < 0) - return false; - m_Offset += len; + } break; } case CPDF_Object::ARRAY: { - if (m_File.AppendString("[") < 0) + if (!m_Archive->WriteString("[")) return false; - m_Offset += 1; const CPDF_Array* p = pObj->AsArray(); for (size_t i = 0; i < p->GetCount(); i++) { CPDF_Object* pElement = p->GetObjectAt(i); if (!pElement->IsInline()) { - if (m_File.AppendString(" ") < 0) - return false; - - int32_t len = m_File.AppendDWord(pElement->GetObjNum()); - if (len < 0 || m_File.AppendString(" 0 R") < 0) + if (!m_Archive->WriteString(" ") || + !m_Archive->WriteDWord(pElement->GetObjNum()) || + !m_Archive->WriteString(" 0 R")) { return false; - m_Offset += len + 5; + } } else if (!WriteDirectObj(objnum, pElement, true)) { return false; } } - if (m_File.AppendString("]") < 0) + if (!m_Archive->WriteString("]")) return false; - - m_Offset += 1; break; } case CPDF_Object::DICTIONARY: { if (!m_pCryptoHandler || pObj == m_pEncryptDict) { - if (!pObj->WriteTo(&m_File, &m_Offset)) + if (!pObj->WriteTo(m_Archive.get())) return false; break; } - if (m_File.AppendString("<<") < 0) + if (!m_Archive->WriteString("<<")) return false; - m_Offset += 2; const CPDF_Dictionary* p = pObj->AsDictionary(); bool bSignDict = p->IsSignatureDict(); for (const auto& it : *p) { bool bSignValue = false; const CFX_ByteString& key = it.first; CPDF_Object* pValue = it.second.get(); - if (m_File.AppendString("/") < 0) + if (!m_Archive->WriteString("/") || + !m_Archive->WriteString(PDF_NameEncode(key).AsStringC())) { return false; - - int32_t len = m_File.AppendString(PDF_NameEncode(key).AsStringC()); - if (len < 0) - return false; - m_Offset += len + 1; + } if (bSignDict && key == "Contents") bSignValue = true; if (!pValue->IsInline()) { - if (m_File.AppendString(" ") < 0) - return false; - - len = m_File.AppendDWord(pValue->GetObjNum()); - if (len < 0 || m_File.AppendString(" 0 R ") < 0) + if (!m_Archive->WriteString(" ") || + !m_Archive->WriteDWord(pValue->GetObjNum()) || + !m_Archive->WriteString(" 0 R ")) { return false; - m_Offset += len + 6; + } } else if (!WriteDirectObj(objnum, pValue, !bSignValue)) { return false; } } - if (m_File.AppendString(">>") < 0) + if (!m_Archive->WriteString(">>")) return false; - - m_Offset += 2; break; } } @@ -346,7 +383,8 @@ bool CPDF_Creator::WriteOldIndirectObject(uint32_t objnum) { if (m_pParser->IsObjectFreeOrNull(objnum)) return true; - m_ObjectOffsets[objnum] = m_Offset; + m_ObjectOffsets[objnum] = m_Archive->CurrentOffset(); + bool bExistInMap = !!m_pDocument->GetIndirectObject(objnum); const uint8_t object_type = m_pParser->GetObjectType(objnum); if (m_pParser->IsVersionUpdated() || m_bSecurityChanged || bExistInMap || @@ -373,26 +411,18 @@ bool CPDF_Creator::WriteOldIndirectObject(uint32_t objnum) { return false; } } else { - int32_t len = m_File.AppendDWord(objnum); - if (len < 0 || m_File.AppendString(" 0 obj ") < 0) - return false; - m_Offset += len + 7; - - if (m_File.AppendBlock(pBuffer, size) < 0) + if (!m_Archive->WriteDWord(objnum) || + !m_Archive->WriteString(" 0 obj ") || + !m_Archive->WriteBlock(pBuffer, size) || + !m_Archive->WriteString("\r\nendobj\r\n")) { return false; - m_Offset += size; - - if (m_File.AppendString("\r\nendobj\r\n") < 0) - return false; - m_Offset += 10; + } } } else { - if (m_File.AppendBlock(pBuffer, size) < 0) - return false; - m_Offset += size; - - if (!AppendObjectNumberToXRef(objnum)) + if (!m_Archive->WriteBlock(pBuffer, size) || + !AppendObjectNumberToXRef(objnum)) { return false; + } } FX_Free(pBuffer); } @@ -418,7 +448,7 @@ bool CPDF_Creator::WriteNewObjs() { if (!pObj) continue; - m_ObjectOffsets[objnum] = m_Offset; + m_ObjectOffsets[objnum] = m_Archive->CurrentOffset(); if (!WriteIndirectObj(pObj)) return false; } @@ -483,9 +513,8 @@ int32_t CPDF_Creator::WriteDoc_Stage1() { } if (m_iStage == 10) { if (!IsIncremental()) { - if (m_File.AppendString("%PDF-1.") < 0) + if (!m_Archive->WriteString("%PDF-1.")) return -1; - m_Offset += 7; int32_t version = 7; if (m_FileVersion) @@ -493,21 +522,15 @@ int32_t CPDF_Creator::WriteDoc_Stage1() { else if (m_pParser) version = m_pParser->GetFileVersion(); - int32_t len = m_File.AppendDWord(version % 10); - if (len < 0) - return -1; - m_Offset += len; - - len = m_File.AppendString("\r\n%\xA1\xB3\xC5\xD7\r\n"); - if (len < 0) + if (!m_Archive->WriteDWord(version % 10) || + !m_Archive->WriteString("\r\n%\xA1\xB3\xC5\xD7\r\n")) { return -1; - m_Offset += len; + } InitOldObjNumOffsets(); m_iStage = 20; } else { - m_Offset = m_pParser->GetFileAccess()->GetSize(); - m_SavedOffset = m_Offset; + m_SavedOffset = m_pParser->GetFileAccess()->GetSize(); m_iStage = 15; } } @@ -519,11 +542,12 @@ int32_t CPDF_Creator::WriteDoc_Stage1() { FX_FILESIZE src_size = m_SavedOffset; while (src_size) { uint32_t block_size = src_size > 4096 ? 4096 : src_size; - if (!pSrcFile->ReadBlock(buffer.data(), m_Offset - src_size, + if (!pSrcFile->ReadBlock(buffer.data(), + m_Archive->CurrentOffset() - src_size, block_size)) { return -1; } - if (m_File.AppendBlock(buffer.data(), block_size) < 0) + if (!m_Archive->WriteBlock(buffer.data(), block_size)) return -1; src_size -= block_size; @@ -580,7 +604,7 @@ int32_t CPDF_Creator::WriteDoc_Stage2() { if (m_iStage == 27) { if (m_pEncryptDict && m_pEncryptDict->IsInline()) { m_dwLastObjNum += 1; - FX_FILESIZE saveOffset = m_Offset; + FX_FILESIZE saveOffset = m_Archive->CurrentOffset(); if (!WriteIndirectObj(m_dwLastObjNum, m_pEncryptDict)) return -1; @@ -599,7 +623,7 @@ int32_t CPDF_Creator::WriteDoc_Stage3() { uint32_t dwLastObjNum = m_dwLastObjNum; if (m_iStage == 80) { - m_XrefStart = m_Offset; + m_XrefStart = m_Archive->CurrentOffset(); if (HasObjectStream()) { m_pXRefStream->End(this, true); m_XrefStart = m_pXRefStream->GetPreviousOffset(); @@ -610,13 +634,13 @@ int32_t CPDF_Creator::WriteDoc_Stage3() { str = pdfium::ContainsKey(m_ObjectOffsets, 1) ? "xref\r\n" : "xref\r\n0 1\r\n0000000000 65535 f\r\n"; - if (m_File.AppendString(str.AsStringC()) < 0) + if (!m_Archive->WriteString(str.AsStringC())) return -1; m_CurObjNum = 1; m_iStage = 81; } else { - if (m_File.AppendString("xref\r\n") < 0) + if (!m_Archive->WriteString("xref\r\n")) return -1; m_CurObjNum = 0; @@ -646,12 +670,12 @@ int32_t CPDF_Creator::WriteDoc_Stage3() { else str.Format("%d %d\r\n", i, j - i); - if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) + if (!m_Archive->WriteBlock(str.c_str(), str.GetLength())) return -1; while (i < j) { str.Format("%010d 00000 n\r\n", m_ObjectOffsets[i++]); - if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) + if (!m_Archive->WriteBlock(str.c_str(), str.GetLength())) return -1; } if (i > dwLastObjNum) @@ -680,13 +704,13 @@ int32_t CPDF_Creator::WriteDoc_Stage3() { else str.Format("%d %d\r\n", objnum, j - i); - if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) + if (!m_Archive->WriteBlock(str.c_str(), str.GetLength())) return -1; while (i < j) { objnum = m_NewObjNumArray[i++]; str.Format("%010d 00000 n\r\n", m_ObjectOffsets[objnum]); - if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) + if (!m_Archive->WriteBlock(str.c_str(), str.GetLength())) return -1; } } @@ -701,11 +725,11 @@ int32_t CPDF_Creator::WriteDoc_Stage4() { if (!HasObjectStream()) { bool bXRefStream = IsIncremental() && m_pParser->IsXRefStream(); if (!bXRefStream) { - if (m_File.AppendString("trailer\r\n<<") < 0) + if (!m_Archive->WriteString("trailer\r\n<<")) return -1; } else { - if (m_File.AppendDWord(m_pDocument->GetLastObjNum() + 1) < 0 || - m_File.AppendString(" 0 obj <<") < 0) { + if (!m_Archive->WriteDWord(m_pDocument->GetLastObjNum() + 1) || + !m_Archive->WriteString(" 0 obj <<")) { return -1; } } @@ -722,147 +746,135 @@ int32_t CPDF_Creator::WriteDoc_Stage4() { key == "XRefStm" || key == "ID") { continue; } - if (m_File.AppendString(("/")) < 0 || - m_File.AppendString(PDF_NameEncode(key).AsStringC()) < 0) { + if (!m_Archive->WriteString(("/")) || + !m_Archive->WriteString(PDF_NameEncode(key).AsStringC())) { return -1; } if (!pValue->IsInline()) { - if (m_File.AppendString(" ") < 0 || - m_File.AppendDWord(pValue->GetObjNum()) < 0 || - m_File.AppendString(" 0 R ") < 0) { + if (!m_Archive->WriteString(" ") || + !m_Archive->WriteDWord(pValue->GetObjNum()) || + !m_Archive->WriteString(" 0 R ")) { return -1; } - } else { - FX_FILESIZE offset = 0; - if (!pValue->WriteTo(&m_File, &offset)) - return -1; + } else if (!pValue->WriteTo(m_Archive.get())) { + return -1; } } } else { - if (m_File.AppendString("\r\n/Root ") < 0 || - m_File.AppendDWord(m_pDocument->GetRoot()->GetObjNum()) < 0 || - m_File.AppendString(" 0 R\r\n") < 0) { + if (!m_Archive->WriteString("\r\n/Root ") || + !m_Archive->WriteDWord(m_pDocument->GetRoot()->GetObjNum()) || + !m_Archive->WriteString(" 0 R\r\n")) { return -1; } if (m_pDocument->GetInfo()) { - if (m_File.AppendString("/Info ") < 0 || - m_File.AppendDWord(m_pDocument->GetInfo()->GetObjNum()) < 0 || - m_File.AppendString(" 0 R\r\n") < 0) { + if (!m_Archive->WriteString("/Info ") || + !m_Archive->WriteDWord(m_pDocument->GetInfo()->GetObjNum()) || + !m_Archive->WriteString(" 0 R\r\n")) { return -1; } } } if (m_pEncryptDict) { - if (m_File.AppendString("/Encrypt") < 0) + if (!m_Archive->WriteString("/Encrypt")) return -1; uint32_t dwObjNum = m_pEncryptDict->GetObjNum(); if (dwObjNum == 0) dwObjNum = m_pDocument->GetLastObjNum() + 1; - if (m_File.AppendString(" ") < 0 || m_File.AppendDWord(dwObjNum) < 0 || - m_File.AppendString(" 0 R ") < 0) { + if (!m_Archive->WriteString(" ") || !m_Archive->WriteDWord(dwObjNum) || + !m_Archive->WriteString(" 0 R ")) { return -1; } } - if (m_File.AppendString("/Size ") < 0 || - m_File.AppendDWord(m_dwLastObjNum + (bXRefStream ? 2 : 1)) < 0) { + if (!m_Archive->WriteString("/Size ") || + !m_Archive->WriteDWord(m_dwLastObjNum + (bXRefStream ? 2 : 1))) { return -1; } if (IsIncremental()) { FX_FILESIZE prev = m_pParser->GetLastXRefOffset(); if (prev) { - if (m_File.AppendString("/Prev ") < 0) + if (!m_Archive->WriteString("/Prev ")) return -1; char offset_buf[20]; memset(offset_buf, 0, sizeof(offset_buf)); FXSYS_i64toa(prev, offset_buf, 10); - if (m_File.AppendBlock(offset_buf, FXSYS_strlen(offset_buf)) < 0) + if (!m_Archive->WriteBlock(offset_buf, FXSYS_strlen(offset_buf))) return -1; } } if (m_pIDArray) { - if (m_File.AppendString(("/ID")) < 0) - return -1; - - FX_FILESIZE offset = 0; - if (!m_pIDArray->WriteTo(&m_File, &offset)) + if (!m_Archive->WriteString(("/ID")) || + !m_pIDArray->WriteTo(m_Archive.get())) { return -1; + } } if (!bXRefStream) { - if (m_File.AppendString(">>") < 0) + if (!m_Archive->WriteString(">>")) return -1; } else { - if (m_File.AppendString("/W[0 4 1]/Index[") < 0) + if (!m_Archive->WriteString("/W[0 4 1]/Index[")) return -1; if (IsIncremental() && m_pParser && m_pParser->GetLastXRefOffset() == 0) { uint32_t i = 0; for (i = 0; i < m_dwLastObjNum; i++) { if (!pdfium::ContainsKey(m_ObjectOffsets, i)) continue; - if (m_File.AppendDWord(i) < 0 || m_File.AppendString(" 1 ") < 0) + if (!m_Archive->WriteDWord(i) || !m_Archive->WriteString(" 1 ")) return -1; } - if (m_File.AppendString("]/Length ") < 0 || - m_File.AppendDWord(m_dwLastObjNum * 5) < 0 || - m_File.AppendString(">>stream\r\n") < 0) { + if (!m_Archive->WriteString("]/Length ") || + !m_Archive->WriteDWord(m_dwLastObjNum * 5) || + !m_Archive->WriteString(">>stream\r\n")) { return -1; } for (i = 0; i < m_dwLastObjNum; i++) { auto it = m_ObjectOffsets.find(i); if (it == m_ObjectOffsets.end()) continue; - OutputIndex(&m_File, it->second); + OutputIndex(m_Archive.get(), it->second); } } else { size_t count = m_NewObjNumArray.size(); size_t i = 0; for (i = 0; i < count; i++) { - if (m_File.AppendDWord(m_NewObjNumArray[i]) < 0 || - m_File.AppendString(" 1 ") < 0) { + if (!m_Archive->WriteDWord(m_NewObjNumArray[i]) || + !m_Archive->WriteString(" 1 ")) { return -1; } } - if (m_File.AppendString("]/Length ") < 0 || - m_File.AppendDWord(count * 5) < 0 || - m_File.AppendString(">>stream\r\n") < 0) { + if (!m_Archive->WriteString("]/Length ") || + !m_Archive->WriteDWord(count * 5) || + !m_Archive->WriteString(">>stream\r\n")) { return -1; } for (i = 0; i < count; ++i) - OutputIndex(&m_File, m_ObjectOffsets[m_NewObjNumArray[i]]); + OutputIndex(m_Archive.get(), m_ObjectOffsets[m_NewObjNumArray[i]]); } - if (m_File.AppendString("\r\nendstream") < 0) + if (!m_Archive->WriteString("\r\nendstream")) return -1; } } - if (m_File.AppendString("\r\nstartxref\r\n") < 0) + if (!m_Archive->WriteString("\r\nstartxref\r\n")) return -1; char offset_buf[20]; memset(offset_buf, 0, sizeof(offset_buf)); FXSYS_i64toa(m_XrefStart, offset_buf, 10); - if (m_File.AppendBlock(offset_buf, FXSYS_strlen(offset_buf)) < 0 || - m_File.AppendString("\r\n%%EOF\r\n") < 0) { + if (!m_Archive->WriteBlock(offset_buf, FXSYS_strlen(offset_buf)) || + !m_Archive->WriteString("\r\n%%EOF\r\n")) { return -1; } - m_File.Flush(); - return m_iStage = 100; -} - -void CPDF_Creator::Clear() { - m_pXRefStream.reset(); - m_File.Clear(); - m_NewObjNumArray.clear(); - m_pIDArray.reset(); + m_iStage = 100; + return m_iStage; } bool CPDF_Creator::Create(uint32_t flags) { m_dwFlags = flags; m_iStage = 0; - m_Offset = 0; m_dwLastObjNum = m_pDocument->GetLastObjNum(); m_ObjectOffsets.clear(); m_NewObjNumArray.clear(); @@ -939,7 +951,6 @@ int32_t CPDF_Creator::Continue() { if (iRet < 1 || m_iStage == 100) { m_iStage = -1; - Clear(); return iRet > 99 ? 0 : (iRet < 1 ? -1 : iRet); } return m_iStage; @@ -952,12 +963,6 @@ bool CPDF_Creator::SetFileVersion(int32_t fileVersion) { return true; } -void CPDF_Creator::IncrementOffset(FX_FILESIZE inc) { - pdfium::base::CheckedNumeric size = m_Offset; - size += inc; - m_Offset = size.ValueOrDie(); -} - void CPDF_Creator::RemoveSecurity() { m_pCryptoHandler.Reset(); m_bSecurityChanged = true; diff --git a/core/fpdfapi/edit/cpdf_creator.h b/core/fpdfapi/edit/cpdf_creator.h index 5f39f5c40f..3d85d5e0a4 100644 --- a/core/fpdfapi/edit/cpdf_creator.h +++ b/core/fpdfapi/edit/cpdf_creator.h @@ -30,7 +30,7 @@ class CPDF_XRefStream; class CPDF_Creator { public: explicit CPDF_Creator(CPDF_Document* pDoc, - const CFX_RetainPtr& pFile); + const CFX_RetainPtr& archive); ~CPDF_Creator(); void RemoveSecurity(); @@ -38,10 +38,8 @@ class CPDF_Creator { int32_t Continue(); bool SetFileVersion(int32_t fileVersion); - CFX_FileBufferArchive* GetFile() { return &m_File; } + IFX_ArchiveStream* GetArchive() { return m_Archive.get(); } - FX_FILESIZE GetOffset() const { return m_Offset; } - void IncrementOffset(FX_FILESIZE inc); uint32_t GetNextObjectNumber() { return ++m_dwLastObjNum; } uint32_t GetLastObjectNumber() const { return m_dwLastObjNum; } CPDF_CryptoHandler* GetCryptoHandler() { return m_pCryptoHandler.Get(); } @@ -102,8 +100,7 @@ class CPDF_Creator { CPDF_Object* m_pMetadata; std::unique_ptr m_pXRefStream; uint32_t m_dwLastObjNum; - CFX_FileBufferArchive m_File; - FX_FILESIZE m_Offset; + std::unique_ptr m_Archive; FX_FILESIZE m_SavedOffset; int32_t m_iStage; uint32_t m_dwFlags; diff --git a/core/fpdfapi/edit/cpdf_objectstream.cpp b/core/fpdfapi/edit/cpdf_objectstream.cpp index 9b636f2e54..208adacf47 100644 --- a/core/fpdfapi/edit/cpdf_objectstream.cpp +++ b/core/fpdfapi/edit/cpdf_objectstream.cpp @@ -51,8 +51,8 @@ FX_FILESIZE CPDF_ObjectStream::End(CPDF_Creator* pCreator) { if (m_Items.empty()) return 0; - CFX_FileBufferArchive* pFile = pCreator->GetFile(); - FX_FILESIZE ObjOffset = pCreator->GetOffset(); + IFX_ArchiveStream* archive = pCreator->GetArchive(); + FX_FILESIZE ObjOffset = archive->CurrentOffset(); if (!m_dwObjNum) m_dwObjNum = pCreator->GetNextObjectNumber(); @@ -60,29 +60,14 @@ FX_FILESIZE CPDF_ObjectStream::End(CPDF_Creator* pCreator) { for (const auto& pair : m_Items) tempBuffer << pair.objnum << " " << pair.offset << " "; - int32_t len = pFile->AppendDWord(m_dwObjNum); - if (len < 0) + if (!archive->WriteDWord(m_dwObjNum) || + !archive->WriteString(" 0 obj\r\n<WriteDWord(pdfium::CollectionSize(m_Items)) || + !archive->WriteString("/First ") || + !archive->WriteDWord(static_cast(tempBuffer.GetLength())) || + !archive->WriteString("/Length ")) { return -1; - pCreator->IncrementOffset(len); - - len = pFile->AppendString(" 0 obj\r\n<IncrementOffset(len); - - len = pFile->AppendDWord(pdfium::CollectionSize(m_Items)); - if (len < 0) - return -1; - pCreator->IncrementOffset(len); - - if (pFile->AppendString("/First ") < 0) - return -1; - - len = pFile->AppendDWord(static_cast(tempBuffer.GetLength())); - if (len < 0 || pFile->AppendString("/Length ") < 0) - return -1; - pCreator->IncrementOffset(len + 15); - + } tempBuffer << m_Buffer; CPDF_FlateEncoder encoder(tempBuffer.GetBuffer(), tempBuffer.GetLength(), @@ -90,26 +75,13 @@ FX_FILESIZE CPDF_ObjectStream::End(CPDF_Creator* pCreator) { CPDF_Encryptor encryptor(pCreator->GetCryptoHandler(), m_dwObjNum, encoder.GetData(), encoder.GetSize()); - len = pFile->AppendDWord(encryptor.GetSize()); - if (len < 0) - return -1; - pCreator->IncrementOffset(len); - - if (pFile->AppendString("/Filter /FlateDecode") < 0) - return -1; - pCreator->IncrementOffset(20); - - len = pFile->AppendString(">>stream\r\n"); - if (len < 0 || - pFile->AppendBlock(encryptor.GetData(), encryptor.GetSize()) < 0) { + if (!archive->WriteDWord(encryptor.GetSize()) || + !archive->WriteString("/Filter /FlateDecode") || + !archive->WriteString(">>stream\r\n") || + !archive->WriteBlock(encryptor.GetData(), encryptor.GetSize()) || + !archive->WriteString("\r\nendstream\r\nendobj\r\n")) { return -1; } - pCreator->IncrementOffset(len + encryptor.GetSize()); - - len = pFile->AppendString("\r\nendstream\r\nendobj\r\n"); - if (len < 0) - return -1; - pCreator->IncrementOffset(len); return ObjOffset; } diff --git a/core/fpdfapi/edit/cpdf_xrefstream.cpp b/core/fpdfapi/edit/cpdf_xrefstream.cpp index 7ec05fd8bc..67793b244d 100644 --- a/core/fpdfapi/edit/cpdf_xrefstream.cpp +++ b/core/fpdfapi/edit/cpdf_xrefstream.cpp @@ -17,11 +17,9 @@ namespace { const int32_t kObjectStreamMaxSize = 200; -int32_t WriteTrailer(CPDF_Document* pDocument, - CFX_FileBufferArchive* pFile, - CPDF_Array* pIDArray) { - FX_FILESIZE offset = 0; - int32_t len = 0; +bool WriteTrailer(CPDF_Document* pDocument, + IFX_ArchiveStream* archive, + CPDF_Array* pIDArray) { CPDF_Parser* pParser = pDocument->GetParser(); if (pParser) { CPDF_Dictionary* p = pParser->GetTrailer(); @@ -35,83 +33,56 @@ int32_t WriteTrailer(CPDF_Document* pDocument, } if (key == "DecodeParms") continue; - if (pFile->AppendString(("/")) < 0) - return -1; - - len = pFile->AppendString(PDF_NameEncode(key).AsStringC()); - if (len < 0) - return -1; - offset += len + 1; + if (!archive->WriteString(("/")) || + !archive->WriteString(PDF_NameEncode(key).AsStringC())) { + return false; + } if (!pValue->IsInline()) { - if (pFile->AppendString(" ") < 0) - return -1; - - len = pFile->AppendDWord(pValue->GetObjNum()); - if (len < 0 || pFile->AppendString(" 0 R ") < 0) - return -1; - offset += len + 6; - } else if (!pValue->WriteTo(pFile, &offset)) { - return -1; + if (!archive->WriteString(" ") || + !archive->WriteDWord(pValue->GetObjNum()) || + !archive->WriteString(" 0 R ")) { + return false; + } + } else if (!pValue->WriteTo(archive)) { + return false; } } if (pIDArray) { - if (pFile->AppendString(("/ID")) < 0) - return -1; - offset += 3; - - if (!pIDArray->WriteTo(pFile, &offset)) - return -1; + if (!archive->WriteString(("/ID")) || !pIDArray->WriteTo(archive)) + return false; } - return offset; + return true; + } + if (!archive->WriteString("\r\n/Root ") || + !archive->WriteDWord(pDocument->GetRoot()->GetObjNum()) || + !archive->WriteString(" 0 R\r\n")) { + return false; } - if (pFile->AppendString("\r\n/Root ") < 0) - return -1; - - len = pFile->AppendDWord(pDocument->GetRoot()->GetObjNum()); - if (len < 0 || pFile->AppendString(" 0 R\r\n") < 0) - return -1; - offset += len + 14; if (pDocument->GetInfo()) { - if (pFile->AppendString("/Info ") < 0) - return -1; - - len = pFile->AppendDWord(pDocument->GetInfo()->GetObjNum()); - if (len < 0 || pFile->AppendString(" 0 R\r\n") < 0) - return -1; - offset += len + 12; + if (!archive->WriteString("/Info ") || + !archive->WriteDWord(pDocument->GetInfo()->GetObjNum()) || + !archive->WriteString(" 0 R\r\n")) { + return false; + } } if (pIDArray) { - if (pFile->AppendString(("/ID")) < 0) - return -1; - offset += 3; - - if (!pIDArray->WriteTo(pFile, &offset)) - return -1; + if (!archive->WriteString(("/ID")) || !pIDArray->WriteTo(archive)) + return false; } - return offset; + return true; } -int32_t WriteEncryptDictObjectReference(uint32_t dwObjNum, - CFX_FileBufferArchive* pFile) { - ASSERT(pFile); - - FX_FILESIZE offset = 0; - int32_t len = 0; - if (pFile->AppendString("/Encrypt") < 0) - return -1; - offset += 8; - - if (pFile->AppendString(" ") < 0) - return -1; +bool WriteEncryptDictObjectReference(uint32_t dwObjNum, + IFX_ArchiveStream* archive) { + ASSERT(archive); - len = pFile->AppendDWord(dwObjNum); - if (len < 0 || pFile->AppendString(" 0 R ") < 0) - return -1; - offset += len + 6; - - return offset; + if (!archive->WriteString("/Encrypt") || !archive->WriteString(" ") || + !archive->WriteDWord(dwObjNum) || !archive->WriteString(" 0 R ")) { + return false; + } + return true; } void AppendIndex0(CFX_ByteTextBuf& buffer, bool bFirstObject) { @@ -255,9 +226,10 @@ bool CPDF_XRefStream::EndObjectStream(CPDF_Creator* pCreator, bool bEOF) { } bool CPDF_XRefStream::GenerateXRefStream(CPDF_Creator* pCreator, bool bEOF) { - FX_FILESIZE offset_tmp = pCreator->GetOffset(); uint32_t objnum = pCreator->GetNextObjectNumber(); - CFX_FileBufferArchive* pFile = pCreator->GetFile(); + IFX_ArchiveStream* archive = pCreator->GetArchive(); + FX_FILESIZE offset_tmp = archive->CurrentOffset(); + if (pCreator->IsIncremental()) { AddObjectNumberToIndexArray(objnum); } else { @@ -271,113 +243,67 @@ bool CPDF_XRefStream::GenerateXRefStream(CPDF_Creator* pCreator, bool bEOF) { AppendIndex1(m_Buffer, offset_tmp); - int32_t len = pFile->AppendDWord(objnum); - if (len < 0) - return false; - pCreator->IncrementOffset(len); - - len = pFile->AppendString(" 0 obj\r\n<WriteDWord(objnum) || + !archive->WriteString(" 0 obj\r\n<IncrementOffset(len); + } if (!pCreator->IsIncremental()) { - if (pFile->AppendDWord(0) < 0) - return false; - - len = pFile->AppendString(" "); - if (len < 0) + if (!archive->WriteDWord(0) || !archive->WriteString(" ") || + !archive->WriteDWord(objnum + 1)) { return false; - pCreator->IncrementOffset(len + 1); - - len = pFile->AppendDWord(objnum + 1); - if (len < 0) - return false; - pCreator->IncrementOffset(len); + } } else { for (const auto& pair : m_IndexArray) { - len = pFile->AppendDWord(pair.objnum); - if (len < 0 || pFile->AppendString(" ") < 0) + if (!archive->WriteDWord(pair.objnum) || !archive->WriteString(" ") || + !archive->WriteDWord(pair.count) || !archive->WriteString(" ")) { return false; - pCreator->IncrementOffset(len + 1); - - len = pFile->AppendDWord(pair.count); - if (len < 0 || pFile->AppendString(" ") < 0) - return false; - pCreator->IncrementOffset(len + 1); + } } } - if (pFile->AppendString("]/Size ") < 0) + if (!archive->WriteString("]/Size ") || !archive->WriteDWord(objnum + 1)) return false; - len = pFile->AppendDWord(objnum + 1); - if (len < 0) - return false; - pCreator->IncrementOffset(len + 7); - if (m_PrevOffset > 0) { - if (pFile->AppendString("/Prev ") < 0) + if (!archive->WriteString("/Prev ")) return false; char offset_buf[20]; memset(offset_buf, 0, sizeof(offset_buf)); FXSYS_i64toa(m_PrevOffset, offset_buf, 10); int32_t offset_len = (int32_t)FXSYS_strlen(offset_buf); - if (pFile->AppendBlock(offset_buf, offset_len) < 0) + if (!archive->WriteBlock(offset_buf, offset_len)) return false; - - pCreator->IncrementOffset(offset_len + 6); } CPDF_FlateEncoder encoder(m_Buffer.GetBuffer(), m_Buffer.GetLength(), true, true); - if (pFile->AppendString("/Filter /FlateDecode") < 0) + if (!archive->WriteString("/Filter /FlateDecode") || + !archive->WriteString("/DecodeParms<>") || + !archive->WriteString("/Length ") || + !archive->WriteDWord(encoder.GetSize())) { return false; - pCreator->IncrementOffset(20); - - len = pFile->AppendString("/DecodeParms<>"); - if (len < 0) - return false; - pCreator->IncrementOffset(len); - - if (pFile->AppendString("/Length ") < 0) - return false; - - len = pFile->AppendDWord(encoder.GetSize()); - if (len < 0) - return false; - pCreator->IncrementOffset(len + 8); + } if (bEOF) { - len = WriteTrailer(pCreator->GetDocument(), pFile, pCreator->GetIDArray()); - if (len < 0) + if (!WriteTrailer(pCreator->GetDocument(), archive, pCreator->GetIDArray())) return false; - pCreator->IncrementOffset(len); if (CPDF_Dictionary* encryptDict = pCreator->GetEncryptDict()) { uint32_t dwEncryptObjNum = encryptDict->GetObjNum(); if (dwEncryptObjNum == 0) dwEncryptObjNum = pCreator->GetEncryptObjectNumber(); - len = WriteEncryptDictObjectReference(dwEncryptObjNum, pFile); - if (len < 0) + if (!WriteEncryptDictObjectReference(dwEncryptObjNum, archive)) return false; - pCreator->IncrementOffset(len); } } - len = pFile->AppendString(">>stream\r\n"); - if (len < 0) - return false; - pCreator->IncrementOffset(len); - - if (pFile->AppendBlock(encoder.GetData(), encoder.GetSize()) < 0) + if (!archive->WriteString(">>stream\r\n") || + !archive->WriteBlock(encoder.GetData(), encoder.GetSize()) || + !archive->WriteString("\r\nendstream\r\nendobj\r\n")) { return false; - - len = pFile->AppendString("\r\nendstream\r\nendobj\r\n"); - if (len < 0) - return false; - pCreator->IncrementOffset(encoder.GetSize() + len); + } m_PrevOffset = offset_tmp; return true; -- cgit v1.2.3