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 +++++----------- core/fpdfapi/parser/cpdf_array.cpp | 28 +-- core/fpdfapi/parser/cpdf_array.h | 3 +- core/fpdfapi/parser/cpdf_boolean.cpp | 13 +- core/fpdfapi/parser/cpdf_boolean.h | 3 +- core/fpdfapi/parser/cpdf_dictionary.cpp | 37 +-- core/fpdfapi/parser/cpdf_dictionary.h | 3 +- core/fpdfapi/parser/cpdf_name.cpp | 14 +- core/fpdfapi/parser/cpdf_name.h | 3 +- core/fpdfapi/parser/cpdf_null.cpp | 8 +- core/fpdfapi/parser/cpdf_null.h | 3 +- core/fpdfapi/parser/cpdf_number.cpp | 13 +- core/fpdfapi/parser/cpdf_number.h | 3 +- core/fpdfapi/parser/cpdf_object.h | 3 +- core/fpdfapi/parser/cpdf_reference.cpp | 14 +- core/fpdfapi/parser/cpdf_reference.h | 3 +- core/fpdfapi/parser/cpdf_stream.cpp | 20 +- core/fpdfapi/parser/cpdf_stream.h | 3 +- core/fpdfapi/parser/cpdf_string.cpp | 12 +- core/fpdfapi/parser/cpdf_string.h | 3 +- core/fxcrt/fx_basic.h | 21 -- core/fxcrt/fx_basic_buffer.cpp | 63 ----- core/fxcrt/fx_stream.h | 8 + 26 files changed, 343 insertions(+), 604 deletions(-) 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; diff --git a/core/fpdfapi/parser/cpdf_array.cpp b/core/fpdfapi/parser/cpdf_array.cpp index aa10588f87..698cd6d0d0 100644 --- a/core/fpdfapi/parser/cpdf_array.cpp +++ b/core/fpdfapi/parser/cpdf_array.cpp @@ -194,31 +194,21 @@ CPDF_Object* CPDF_Array::Add(std::unique_ptr pObj) { return pRet; } -bool CPDF_Array::WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const { - if (archive->AppendString("[") < 0) +bool CPDF_Array::WriteTo(IFX_ArchiveStream* archive) const { + if (!archive->WriteString("[")) return false; - *offset += 1; for (size_t i = 0; i < GetCount(); ++i) { CPDF_Object* pElement = GetObjectAt(i); if (!pElement->IsInline()) { - if (archive->AppendString(" ") < 0) - return false; - - int32_t len = archive->AppendDWord(pElement->GetObjNum()); - if (len < 0) - return false; - if (archive->AppendString(" 0 R") < 0) - return false; - *offset += len + 5; - } else { - if (!pElement->WriteTo(archive, offset)) + if (!archive->WriteString(" ") || + !archive->WriteDWord(pElement->GetObjNum()) || + !archive->WriteString(" 0 R")) { return false; + } + } else if (!pElement->WriteTo(archive)) { + return false; } } - if (archive->AppendString("]") < 0) - return false; - *offset += 1; - return true; + return archive->WriteString("]"); } diff --git a/core/fpdfapi/parser/cpdf_array.h b/core/fpdfapi/parser/cpdf_array.h index b788d1c075..aff65d1454 100644 --- a/core/fpdfapi/parser/cpdf_array.h +++ b/core/fpdfapi/parser/cpdf_array.h @@ -34,8 +34,7 @@ class CPDF_Array : public CPDF_Object { bool IsArray() const override; CPDF_Array* AsArray() override; const CPDF_Array* AsArray() const override; - bool WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; bool IsEmpty() const { return m_Objects.empty(); } size_t GetCount() const { return m_Objects.size(); } diff --git a/core/fpdfapi/parser/cpdf_boolean.cpp b/core/fpdfapi/parser/cpdf_boolean.cpp index 1cee3a3a49..eb01c06332 100644 --- a/core/fpdfapi/parser/cpdf_boolean.cpp +++ b/core/fpdfapi/parser/cpdf_boolean.cpp @@ -45,14 +45,7 @@ const CPDF_Boolean* CPDF_Boolean::AsBoolean() const { return this; } -bool CPDF_Boolean::WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const { - if (archive->AppendString(" ") < 0) - return false; - - int32_t len = archive->AppendString(GetString().AsStringC()); - if (len < 0) - return false; - *offset += len + 1; - return true; +bool CPDF_Boolean::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString(" ") && + archive->WriteString(GetString().AsStringC()); } diff --git a/core/fpdfapi/parser/cpdf_boolean.h b/core/fpdfapi/parser/cpdf_boolean.h index e859f4cf9c..2dd1486b6a 100644 --- a/core/fpdfapi/parser/cpdf_boolean.h +++ b/core/fpdfapi/parser/cpdf_boolean.h @@ -28,8 +28,7 @@ class CPDF_Boolean : public CPDF_Object { bool IsBoolean() const override; CPDF_Boolean* AsBoolean() override; const CPDF_Boolean* AsBoolean() const override; - bool WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; protected: bool m_bValue; diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp index 7d84083829..cbefb5d56d 100644 --- a/core/fpdfapi/parser/cpdf_dictionary.cpp +++ b/core/fpdfapi/parser/cpdf_dictionary.cpp @@ -239,40 +239,27 @@ CFX_ByteString CPDF_Dictionary::MaybeIntern(const CFX_ByteString& str) { return m_pPool ? m_pPool->Intern(str) : str; } -bool CPDF_Dictionary::WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const { - if (archive->AppendString("<<") < 0) +bool CPDF_Dictionary::WriteTo(IFX_ArchiveStream* archive) const { + if (!archive->WriteString("<<")) return false; - *offset += 2; for (const auto& it : *this) { const CFX_ByteString& key = it.first; CPDF_Object* pValue = it.second.get(); - if (archive->AppendString("/") < 0) + if (!archive->WriteString("/") || + !archive->WriteString(PDF_NameEncode(key).AsStringC())) { return false; - - int32_t len = archive->AppendString(PDF_NameEncode(key).AsStringC()); - if (len < 0) - return false; - *offset += len + 1; + } if (!pValue->IsInline()) { - if (archive->AppendString(" ") < 0) - return false; - - len = archive->AppendDWord(pValue->GetObjNum()); - if (len < 0) - return false; - if (archive->AppendString(" 0 R") < 0) - return false; - *offset += len + 5; - } else { - if (!pValue->WriteTo(archive, offset)) + if (!archive->WriteString(" ") || + !archive->WriteDWord(pValue->GetObjNum()) || + !archive->WriteString(" 0 R")) { return false; + } + } else if (!pValue->WriteTo(archive)) { + return false; } } - if (archive->AppendString(">>") < 0) - return false; - *offset += 2; - return true; + return archive->WriteString(">>"); } diff --git a/core/fpdfapi/parser/cpdf_dictionary.h b/core/fpdfapi/parser/cpdf_dictionary.h index e4144c1524..f741299d2d 100644 --- a/core/fpdfapi/parser/cpdf_dictionary.h +++ b/core/fpdfapi/parser/cpdf_dictionary.h @@ -37,8 +37,7 @@ class CPDF_Dictionary : public CPDF_Object { bool IsDictionary() const override; CPDF_Dictionary* AsDictionary() override; const CPDF_Dictionary* AsDictionary() const override; - bool WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; size_t GetCount() const { return m_Map.size(); } CPDF_Object* GetObjectFor(const CFX_ByteString& key) const; diff --git a/core/fpdfapi/parser/cpdf_name.cpp b/core/fpdfapi/parser/cpdf_name.cpp index 74c83b9d28..0287b7ab17 100644 --- a/core/fpdfapi/parser/cpdf_name.cpp +++ b/core/fpdfapi/parser/cpdf_name.cpp @@ -50,15 +50,7 @@ CFX_WideString CPDF_Name::GetUnicodeText() const { return PDF_DecodeText(m_Name); } -bool CPDF_Name::WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const { - if (archive->AppendString("/") < 0) - return false; - - CFX_ByteString str = GetString(); - int32_t len = archive->AppendString(PDF_NameEncode(str).AsStringC()); - if (len < 0) - return false; - *offset += len + 1; - return true; +bool CPDF_Name::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString("/") && + archive->WriteString(PDF_NameEncode(GetString()).AsStringC()); } diff --git a/core/fpdfapi/parser/cpdf_name.h b/core/fpdfapi/parser/cpdf_name.h index 8855f9785c..616f35f9bc 100644 --- a/core/fpdfapi/parser/cpdf_name.h +++ b/core/fpdfapi/parser/cpdf_name.h @@ -27,8 +27,7 @@ class CPDF_Name : public CPDF_Object { bool IsName() const override; CPDF_Name* AsName() override; const CPDF_Name* AsName() const override; - bool WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; protected: CFX_ByteString m_Name; diff --git a/core/fpdfapi/parser/cpdf_null.cpp b/core/fpdfapi/parser/cpdf_null.cpp index b5e07e0c55..254c86fd7a 100644 --- a/core/fpdfapi/parser/cpdf_null.cpp +++ b/core/fpdfapi/parser/cpdf_null.cpp @@ -17,10 +17,6 @@ std::unique_ptr CPDF_Null::Clone() const { return pdfium::MakeUnique(); } -bool CPDF_Null::WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const { - if (archive->AppendString(" null") < 0) - return false; - *offset += 5; - return true; +bool CPDF_Null::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString(" null"); } diff --git a/core/fpdfapi/parser/cpdf_null.h b/core/fpdfapi/parser/cpdf_null.h index b6b781b01a..92917281fb 100644 --- a/core/fpdfapi/parser/cpdf_null.h +++ b/core/fpdfapi/parser/cpdf_null.h @@ -18,8 +18,7 @@ class CPDF_Null : public CPDF_Object { // CPDF_Object. Type GetType() const override; std::unique_ptr Clone() const override; - bool WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; }; #endif // CORE_FPDFAPI_PARSER_CPDF_NULL_H_ diff --git a/core/fpdfapi/parser/cpdf_number.cpp b/core/fpdfapi/parser/cpdf_number.cpp index 24665fff60..73d689fffe 100644 --- a/core/fpdfapi/parser/cpdf_number.cpp +++ b/core/fpdfapi/parser/cpdf_number.cpp @@ -56,14 +56,7 @@ CFX_ByteString CPDF_Number::GetString() const { : CFX_ByteString::FormatFloat(m_Float); } -bool CPDF_Number::WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const { - if (archive->AppendString(" ") < 0) - return false; - - int32_t len = archive->AppendString(GetString().AsStringC()); - if (len < 0) - return false; - *offset += len + 1; - return true; +bool CPDF_Number::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString(" ") && + archive->WriteString(GetString().AsStringC()); } diff --git a/core/fpdfapi/parser/cpdf_number.h b/core/fpdfapi/parser/cpdf_number.h index a5d866f835..57f82274cb 100644 --- a/core/fpdfapi/parser/cpdf_number.h +++ b/core/fpdfapi/parser/cpdf_number.h @@ -31,8 +31,7 @@ class CPDF_Number : public CPDF_Object { bool IsNumber() const override; CPDF_Number* AsNumber() override; const CPDF_Number* AsNumber() const override; - bool WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; bool IsInteger() const { return m_bInteger; } diff --git a/core/fpdfapi/parser/cpdf_object.h b/core/fpdfapi/parser/cpdf_object.h index 8194256f5a..b0c1adf955 100644 --- a/core/fpdfapi/parser/cpdf_object.h +++ b/core/fpdfapi/parser/cpdf_object.h @@ -89,8 +89,7 @@ class CPDF_Object { virtual CPDF_String* AsString(); virtual const CPDF_String* AsString() const; - virtual bool WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const = 0; + virtual bool WriteTo(IFX_ArchiveStream* archive) const = 0; protected: friend class CPDF_Array; diff --git a/core/fpdfapi/parser/cpdf_reference.cpp b/core/fpdfapi/parser/cpdf_reference.cpp index 560fd27934..ff0442b6f5 100644 --- a/core/fpdfapi/parser/cpdf_reference.cpp +++ b/core/fpdfapi/parser/cpdf_reference.cpp @@ -83,15 +83,7 @@ CPDF_Object* CPDF_Reference::GetDirect() const { : nullptr; } -bool CPDF_Reference::WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const { - if (archive->AppendString(" ") < 0) - return false; - int32_t len = archive->AppendDWord(GetRefObjNum()); - if (len < 0) - return false; - if (archive->AppendString(" 0 R ") < 0) - return false; - *offset += len + 6; - return true; +bool CPDF_Reference::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString(" ") && archive->WriteDWord(GetRefObjNum()) && + archive->WriteString(" 0 R "); } diff --git a/core/fpdfapi/parser/cpdf_reference.h b/core/fpdfapi/parser/cpdf_reference.h index 4830cb5bf6..83bb0b48e7 100644 --- a/core/fpdfapi/parser/cpdf_reference.h +++ b/core/fpdfapi/parser/cpdf_reference.h @@ -30,8 +30,7 @@ class CPDF_Reference : public CPDF_Object { bool IsReference() const override; CPDF_Reference* AsReference() override; const CPDF_Reference* AsReference() const override; - bool WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; CPDF_IndirectObjectHolder* GetObjList() const { return m_pObjList; } uint32_t GetRefObjNum() const { return m_RefObjNum; } diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp index 7e2529e1d7..69a87e6d2e 100644 --- a/core/fpdfapi/parser/cpdf_stream.cpp +++ b/core/fpdfapi/parser/cpdf_stream.cpp @@ -132,24 +132,12 @@ CFX_WideString CPDF_Stream::GetUnicodeText() const { return PDF_DecodeText(pAcc->GetData(), pAcc->GetSize()); } -bool CPDF_Stream::WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const { - if (!GetDict()->WriteTo(archive, offset)) +bool CPDF_Stream::WriteTo(IFX_ArchiveStream* archive) const { + if (!GetDict()->WriteTo(archive) || !archive->WriteString("stream\r\n")) return false; - if (archive->AppendString("stream\r\n") < 0) - return false; - *offset += 8; auto pAcc = pdfium::MakeRetain(this); pAcc->LoadAllData(true); - if (archive->AppendBlock(pAcc->GetData(), pAcc->GetSize()) < 0) - return false; - *offset += pAcc->GetSize(); - - int32_t len = archive->AppendString("\r\nendstream"); - if (len < 0) - return false; - - *offset += len; - return true; + return archive->WriteBlock(pAcc->GetData(), pAcc->GetSize()) && + archive->WriteString("\r\nendstream"); } diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h index 4f76953efe..82cc01aef3 100644 --- a/core/fpdfapi/parser/cpdf_stream.h +++ b/core/fpdfapi/parser/cpdf_stream.h @@ -33,8 +33,7 @@ class CPDF_Stream : public CPDF_Object { bool IsStream() const override; CPDF_Stream* AsStream() override; const CPDF_Stream* AsStream() const override; - bool WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; uint32_t GetRawSize() const { return m_dwSize; } uint8_t* GetRawData() const { return m_pDataBuf.get(); } diff --git a/core/fpdfapi/parser/cpdf_string.cpp b/core/fpdfapi/parser/cpdf_string.cpp index 01cf3ff1b0..74a2733fc5 100644 --- a/core/fpdfapi/parser/cpdf_string.cpp +++ b/core/fpdfapi/parser/cpdf_string.cpp @@ -65,13 +65,7 @@ CFX_WideString CPDF_String::GetUnicodeText() const { return PDF_DecodeText(m_String); } -bool CPDF_String::WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const { - CFX_ByteString str = GetString(); - int32_t len = - archive->AppendString(PDF_EncodeString(str, IsHex()).AsStringC()); - if (len < 0) - return false; - *offset += len; - return true; +bool CPDF_String::WriteTo(IFX_ArchiveStream* archive) const { + return archive->WriteString( + PDF_EncodeString(GetString(), IsHex()).AsStringC()); } diff --git a/core/fpdfapi/parser/cpdf_string.h b/core/fpdfapi/parser/cpdf_string.h index f895535a92..ccd6f530c1 100644 --- a/core/fpdfapi/parser/cpdf_string.h +++ b/core/fpdfapi/parser/cpdf_string.h @@ -33,8 +33,7 @@ class CPDF_String : public CPDF_Object { bool IsString() const override; CPDF_String* AsString() override; const CPDF_String* AsString() const override; - bool WriteTo(CFX_FileBufferArchive* archive, - FX_FILESIZE* offset) const override; + bool WriteTo(IFX_ArchiveStream* archive) const override; bool IsHex() const { return m_bHex; } diff --git a/core/fxcrt/fx_basic.h b/core/fxcrt/fx_basic.h index 8669c66f5e..e856a3e0ba 100644 --- a/core/fxcrt/fx_basic.h +++ b/core/fxcrt/fx_basic.h @@ -110,27 +110,6 @@ class CFX_WideTextBuf : public CFX_BinaryBuf { CFX_WideTextBuf& operator<<(const CFX_WideTextBuf& buf); }; -class CFX_FileBufferArchive { - public: - CFX_FileBufferArchive(); - ~CFX_FileBufferArchive(); - - void Clear(); - bool Flush(); - int32_t AppendBlock(const void* pBuf, size_t size); - int32_t AppendByte(uint8_t byte); - int32_t AppendDWord(uint32_t i); - int32_t AppendString(const CFX_ByteStringC& lpsz); - void AttachFile(const CFX_RetainPtr& pFile); - - private: - static const size_t kBufSize = 32768; - - size_t m_Length; - std::unique_ptr m_pBuffer; - CFX_RetainPtr m_pFile; -}; - class CFX_UTF8Decoder { public: CFX_UTF8Decoder() { m_PendingBytes = 0; } diff --git a/core/fxcrt/fx_basic_buffer.cpp b/core/fxcrt/fx_basic_buffer.cpp index 13057f1670..36da3f4053 100644 --- a/core/fxcrt/fx_basic_buffer.cpp +++ b/core/fxcrt/fx_basic_buffer.cpp @@ -220,66 +220,3 @@ uint32_t CFX_BitStream::GetBits(uint32_t nBits) { m_BitPos += nBits; return result; } - -CFX_FileBufferArchive::CFX_FileBufferArchive() - : m_Length(0), m_pFile(nullptr) {} - -CFX_FileBufferArchive::~CFX_FileBufferArchive() {} - -void CFX_FileBufferArchive::Clear() { - m_Length = 0; - m_pBuffer.reset(); - m_pFile.Reset(); -} - -bool CFX_FileBufferArchive::Flush() { - size_t nRemaining = m_Length; - m_Length = 0; - if (!m_pFile) - return false; - if (!m_pBuffer || !nRemaining) - return true; - return m_pFile->WriteBlock(m_pBuffer.get(), nRemaining); -} - -int32_t CFX_FileBufferArchive::AppendBlock(const void* pBuf, size_t size) { - if (!pBuf || size < 1) - return 0; - - if (!m_pBuffer) - m_pBuffer.reset(FX_Alloc(uint8_t, kBufSize)); - - const uint8_t* buffer = reinterpret_cast(pBuf); - size_t temp_size = size; - while (temp_size) { - size_t buf_size = std::min(kBufSize - m_Length, temp_size); - memcpy(m_pBuffer.get() + m_Length, buffer, buf_size); - m_Length += buf_size; - if (m_Length == kBufSize && !Flush()) - return -1; - - temp_size -= buf_size; - buffer += buf_size; - } - return pdfium::base::checked_cast(size); -} - -int32_t CFX_FileBufferArchive::AppendByte(uint8_t byte) { - return AppendBlock(&byte, 1); -} - -int32_t CFX_FileBufferArchive::AppendDWord(uint32_t i) { - char buf[32]; - FXSYS_itoa(i, buf, 10); - return AppendBlock(buf, (size_t)FXSYS_strlen(buf)); -} - -int32_t CFX_FileBufferArchive::AppendString(const CFX_ByteStringC& lpsz) { - return AppendBlock(lpsz.raw_str(), lpsz.GetLength()); -} - -void CFX_FileBufferArchive::AttachFile( - const CFX_RetainPtr& pFile) { - ASSERT(pFile); - m_pFile = pFile; -} diff --git a/core/fxcrt/fx_stream.h b/core/fxcrt/fx_stream.h index 9e3277720d..5237a7cb94 100644 --- a/core/fxcrt/fx_stream.h +++ b/core/fxcrt/fx_stream.h @@ -44,6 +44,14 @@ class IFX_WriteStream : virtual public CFX_Retainable { virtual bool WriteBlock(const void* pData, size_t size) = 0; }; +class IFX_ArchiveStream : public IFX_WriteStream { + public: + virtual bool WriteByte(uint8_t byte) = 0; + virtual bool WriteDWord(uint32_t i) = 0; + virtual bool WriteString(const CFX_ByteStringC& str) = 0; + virtual FX_FILESIZE CurrentOffset() const = 0; +}; + class IFX_ReadStream : virtual public CFX_Retainable { public: virtual bool IsEOF() = 0; -- cgit v1.2.3