Home | History | Annotate | Download | only in edit
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/fpdfapi/edit/editint.h"
      8 
      9 #include <memory>
     10 #include <vector>
     11 
     12 #include "core/fpdfapi/edit/cpdf_creator.h"
     13 #include "core/fpdfapi/parser/cpdf_array.h"
     14 #include "core/fpdfapi/parser/cpdf_crypto_handler.h"
     15 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     16 #include "core/fpdfapi/parser/cpdf_document.h"
     17 #include "core/fpdfapi/parser/cpdf_name.h"
     18 #include "core/fpdfapi/parser/cpdf_number.h"
     19 #include "core/fpdfapi/parser/cpdf_parser.h"
     20 #include "core/fpdfapi/parser/cpdf_reference.h"
     21 #include "core/fpdfapi/parser/cpdf_security_handler.h"
     22 #include "core/fpdfapi/parser/cpdf_stream.h"
     23 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
     24 #include "core/fpdfapi/parser/cpdf_string.h"
     25 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
     26 #include "core/fxcrt/cfx_maybe_owned.h"
     27 #include "core/fxcrt/fx_ext.h"
     28 #include "third_party/base/ptr_util.h"
     29 #include "third_party/base/stl_util.h"
     30 
     31 #define PDF_OBJECTSTREAM_MAXLENGTH (256 * 1024)
     32 #define PDF_XREFSTREAM_MAXSIZE 10000
     33 
     34 #define FX_GETBYTEOFFSET32(a) 0
     35 #define FX_GETBYTEOFFSET40(a) 0
     36 #define FX_GETBYTEOFFSET48(a) 0
     37 #define FX_GETBYTEOFFSET56(a) 0
     38 #define FX_GETBYTEOFFSET24(a) ((uint8_t)(a >> 24))
     39 #define FX_GETBYTEOFFSET16(a) ((uint8_t)(a >> 16))
     40 #define FX_GETBYTEOFFSET8(a) ((uint8_t)(a >> 8))
     41 #define FX_GETBYTEOFFSET0(a) ((uint8_t)(a))
     42 
     43 // TODO(ochang): Make helper for appending "objnum 0 R ".
     44 
     45 namespace {
     46 
     47 int32_t PDF_CreatorAppendObject(const CPDF_Object* pObj,
     48                                 CFX_FileBufferArchive* pFile,
     49                                 FX_FILESIZE& offset) {
     50   int32_t len = 0;
     51   if (!pObj) {
     52     if (pFile->AppendString(" null") < 0) {
     53       return -1;
     54     }
     55     offset += 5;
     56     return 1;
     57   }
     58   switch (pObj->GetType()) {
     59     case CPDF_Object::NULLOBJ:
     60       if (pFile->AppendString(" null") < 0) {
     61         return -1;
     62       }
     63       offset += 5;
     64       break;
     65     case CPDF_Object::BOOLEAN:
     66     case CPDF_Object::NUMBER:
     67       if (pFile->AppendString(" ") < 0) {
     68         return -1;
     69       }
     70       if ((len = pFile->AppendString(pObj->GetString().AsStringC())) < 0) {
     71         return -1;
     72       }
     73       offset += len + 1;
     74       break;
     75     case CPDF_Object::STRING: {
     76       CFX_ByteString str = pObj->GetString();
     77       bool bHex = pObj->AsString()->IsHex();
     78       if ((len = pFile->AppendString(PDF_EncodeString(str, bHex).AsStringC())) <
     79           0) {
     80         return -1;
     81       }
     82       offset += len;
     83       break;
     84     }
     85     case CPDF_Object::NAME: {
     86       if (pFile->AppendString("/") < 0) {
     87         return -1;
     88       }
     89       CFX_ByteString str = pObj->GetString();
     90       if ((len = pFile->AppendString(PDF_NameEncode(str).AsStringC())) < 0) {
     91         return -1;
     92       }
     93       offset += len + 1;
     94       break;
     95     }
     96     case CPDF_Object::REFERENCE: {
     97       if (pFile->AppendString(" ") < 0)
     98         return -1;
     99       if ((len = pFile->AppendDWord(pObj->AsReference()->GetRefObjNum())) < 0)
    100         return -1;
    101       if (pFile->AppendString(" 0 R ") < 0)
    102         return -1;
    103       offset += len + 6;
    104       break;
    105     }
    106     case CPDF_Object::ARRAY: {
    107       if (pFile->AppendString("[") < 0) {
    108         return -1;
    109       }
    110       offset += 1;
    111       const CPDF_Array* p = pObj->AsArray();
    112       for (size_t i = 0; i < p->GetCount(); i++) {
    113         CPDF_Object* pElement = p->GetObjectAt(i);
    114         if (!pElement->IsInline()) {
    115           if (pFile->AppendString(" ") < 0) {
    116             return -1;
    117           }
    118           if ((len = pFile->AppendDWord(pElement->GetObjNum())) < 0) {
    119             return -1;
    120           }
    121           if (pFile->AppendString(" 0 R") < 0) {
    122             return -1;
    123           }
    124           offset += len + 5;
    125         } else {
    126           if (PDF_CreatorAppendObject(pElement, pFile, offset) < 0) {
    127             return -1;
    128           }
    129         }
    130       }
    131       if (pFile->AppendString("]") < 0) {
    132         return -1;
    133       }
    134       offset += 1;
    135       break;
    136     }
    137     case CPDF_Object::DICTIONARY: {
    138       if (pFile->AppendString("<<") < 0) {
    139         return -1;
    140       }
    141       offset += 2;
    142       const CPDF_Dictionary* p = pObj->AsDictionary();
    143       for (const auto& it : *p) {
    144         const CFX_ByteString& key = it.first;
    145         CPDF_Object* pValue = it.second.get();
    146         if (pFile->AppendString("/") < 0) {
    147           return -1;
    148         }
    149         if ((len = pFile->AppendString(PDF_NameEncode(key).AsStringC())) < 0) {
    150           return -1;
    151         }
    152         offset += len + 1;
    153         if (!pValue->IsInline()) {
    154           if (pFile->AppendString(" ") < 0) {
    155             return -1;
    156           }
    157           if ((len = pFile->AppendDWord(pValue->GetObjNum())) < 0) {
    158             return -1;
    159           }
    160           if (pFile->AppendString(" 0 R") < 0) {
    161             return -1;
    162           }
    163           offset += len + 5;
    164         } else {
    165           if (PDF_CreatorAppendObject(pValue, pFile, offset) < 0) {
    166             return -1;
    167           }
    168         }
    169       }
    170       if (pFile->AppendString(">>") < 0) {
    171         return -1;
    172       }
    173       offset += 2;
    174       break;
    175     }
    176     case CPDF_Object::STREAM: {
    177       const CPDF_Stream* p = pObj->AsStream();
    178       if (PDF_CreatorAppendObject(p->GetDict(), pFile, offset) < 0) {
    179         return -1;
    180       }
    181       if (pFile->AppendString("stream\r\n") < 0) {
    182         return -1;
    183       }
    184       offset += 8;
    185       CPDF_StreamAcc acc;
    186       acc.LoadAllData(p, true);
    187       if (pFile->AppendBlock(acc.GetData(), acc.GetSize()) < 0) {
    188         return -1;
    189       }
    190       offset += acc.GetSize();
    191       if ((len = pFile->AppendString("\r\nendstream")) < 0) {
    192         return -1;
    193       }
    194       offset += len;
    195       break;
    196     }
    197     default:
    198       ASSERT(false);
    199       break;
    200   }
    201   return 1;
    202 }
    203 
    204 int32_t PDF_CreatorWriteTrailer(CPDF_Document* pDocument,
    205                                 CFX_FileBufferArchive* pFile,
    206                                 CPDF_Array* pIDArray) {
    207   FX_FILESIZE offset = 0;
    208   int32_t len = 0;
    209   CPDF_Parser* pParser = pDocument->GetParser();
    210   if (pParser) {
    211     CPDF_Dictionary* p = pParser->GetTrailer();
    212     for (const auto& it : *p) {
    213       const CFX_ByteString& key = it.first;
    214       CPDF_Object* pValue = it.second.get();
    215       if (key == "Encrypt" || key == "Size" || key == "Filter" ||
    216           key == "Index" || key == "Length" || key == "Prev" || key == "W" ||
    217           key == "XRefStm" || key == "Type" || key == "ID") {
    218         continue;
    219       }
    220       if (key == "DecodeParms")
    221         continue;
    222 
    223       if (pFile->AppendString(("/")) < 0) {
    224         return -1;
    225       }
    226       if ((len = pFile->AppendString(PDF_NameEncode(key).AsStringC())) < 0) {
    227         return -1;
    228       }
    229       offset += len + 1;
    230       if (!pValue->IsInline()) {
    231         if (pFile->AppendString(" ") < 0) {
    232           return -1;
    233         }
    234         if ((len = pFile->AppendDWord(pValue->GetObjNum())) < 0) {
    235           return -1;
    236         }
    237         if (pFile->AppendString(" 0 R ") < 0) {
    238           return -1;
    239         }
    240         offset += len + 6;
    241       } else {
    242         if (PDF_CreatorAppendObject(pValue, pFile, offset) < 0) {
    243           return -1;
    244         }
    245       }
    246     }
    247     if (pIDArray) {
    248       if (pFile->AppendString(("/ID")) < 0) {
    249         return -1;
    250       }
    251       offset += 3;
    252       if (PDF_CreatorAppendObject(pIDArray, pFile, offset) < 0) {
    253         return -1;
    254       }
    255     }
    256     return offset;
    257   }
    258   if (pFile->AppendString("\r\n/Root ") < 0) {
    259     return -1;
    260   }
    261   if ((len = pFile->AppendDWord(pDocument->GetRoot()->GetObjNum())) < 0) {
    262     return -1;
    263   }
    264   if (pFile->AppendString(" 0 R\r\n") < 0) {
    265     return -1;
    266   }
    267   offset += len + 14;
    268   if (pDocument->GetInfo()) {
    269     if (pFile->AppendString("/Info ") < 0) {
    270       return -1;
    271     }
    272     if ((len = pFile->AppendDWord(pDocument->GetInfo()->GetObjNum())) < 0) {
    273       return -1;
    274     }
    275     if (pFile->AppendString(" 0 R\r\n") < 0) {
    276       return -1;
    277     }
    278     offset += len + 12;
    279   }
    280   if (pIDArray) {
    281     if (pFile->AppendString(("/ID")) < 0) {
    282       return -1;
    283     }
    284     offset += 3;
    285     if (PDF_CreatorAppendObject(pIDArray, pFile, offset) < 0) {
    286       return -1;
    287     }
    288   }
    289   return offset;
    290 }
    291 
    292 int32_t PDF_CreatorWriteEncrypt(const CPDF_Dictionary* pEncryptDict,
    293                                 uint32_t dwObjNum,
    294                                 CFX_FileBufferArchive* pFile) {
    295   if (!pEncryptDict) {
    296     return 0;
    297   }
    298   ASSERT(pFile);
    299   FX_FILESIZE offset = 0;
    300   int32_t len = 0;
    301   if (pFile->AppendString("/Encrypt") < 0) {
    302     return -1;
    303   }
    304   offset += 8;
    305   if (pFile->AppendString(" ") < 0) {
    306     return -1;
    307   }
    308   if ((len = pFile->AppendDWord(dwObjNum)) < 0) {
    309     return -1;
    310   }
    311   if (pFile->AppendString(" 0 R ") < 0) {
    312     return -1;
    313   }
    314   offset += len + 6;
    315   return offset;
    316 }
    317 
    318 std::vector<uint8_t> PDF_GenerateFileID(uint32_t dwSeed1, uint32_t dwSeed2) {
    319   std::vector<uint8_t> buffer(sizeof(uint32_t) * 4);
    320   uint32_t* pBuffer = reinterpret_cast<uint32_t*>(buffer.data());
    321   void* pContext = FX_Random_MT_Start(dwSeed1);
    322   for (int i = 0; i < 2; ++i)
    323     *pBuffer++ = FX_Random_MT_Generate(pContext);
    324   FX_Random_MT_Close(pContext);
    325   pContext = FX_Random_MT_Start(dwSeed2);
    326   for (int i = 0; i < 2; ++i)
    327     *pBuffer++ = FX_Random_MT_Generate(pContext);
    328   FX_Random_MT_Close(pContext);
    329   return buffer;
    330 }
    331 
    332 void AppendIndex0(CFX_ByteTextBuf& buffer, bool bFirstObject) {
    333   buffer.AppendByte(0);
    334   buffer.AppendByte(0);
    335   buffer.AppendByte(0);
    336   buffer.AppendByte(0);
    337   buffer.AppendByte(0);
    338   const uint8_t byte = bFirstObject ? 0xFF : 0;
    339   buffer.AppendByte(byte);
    340   buffer.AppendByte(byte);
    341 }
    342 
    343 void AppendIndex1(CFX_ByteTextBuf& buffer, FX_FILESIZE offset) {
    344   buffer.AppendByte(1);
    345   buffer.AppendByte(FX_GETBYTEOFFSET24(offset));
    346   buffer.AppendByte(FX_GETBYTEOFFSET16(offset));
    347   buffer.AppendByte(FX_GETBYTEOFFSET8(offset));
    348   buffer.AppendByte(FX_GETBYTEOFFSET0(offset));
    349   buffer.AppendByte(0);
    350   buffer.AppendByte(0);
    351 }
    352 
    353 void AppendIndex2(CFX_ByteTextBuf& buffer, uint32_t objnum, int32_t index) {
    354   buffer.AppendByte(2);
    355   buffer.AppendByte(FX_GETBYTEOFFSET24(objnum));
    356   buffer.AppendByte(FX_GETBYTEOFFSET16(objnum));
    357   buffer.AppendByte(FX_GETBYTEOFFSET8(objnum));
    358   buffer.AppendByte(FX_GETBYTEOFFSET0(objnum));
    359   buffer.AppendByte(FX_GETBYTEOFFSET8(index));
    360   buffer.AppendByte(FX_GETBYTEOFFSET0(index));
    361 }
    362 
    363 bool IsXRefNeedEnd(CPDF_XRefStream* pXRef, uint32_t flag) {
    364   if (!(flag & FPDFCREATE_INCREMENTAL))
    365     return false;
    366 
    367   uint32_t iCount = 0;
    368   for (const auto& pair : pXRef->m_IndexArray)
    369     iCount += pair.count;
    370 
    371   return iCount >= PDF_XREFSTREAM_MAXSIZE;
    372 }
    373 
    374 int32_t OutputIndex(CFX_FileBufferArchive* pFile, FX_FILESIZE offset) {
    375   if (sizeof(offset) > 4) {
    376     if (FX_GETBYTEOFFSET32(offset)) {
    377       if (pFile->AppendByte(FX_GETBYTEOFFSET56(offset)) < 0)
    378         return -1;
    379       if (pFile->AppendByte(FX_GETBYTEOFFSET48(offset)) < 0)
    380         return -1;
    381       if (pFile->AppendByte(FX_GETBYTEOFFSET40(offset)) < 0)
    382         return -1;
    383       if (pFile->AppendByte(FX_GETBYTEOFFSET32(offset)) < 0)
    384         return -1;
    385     }
    386   }
    387   if (pFile->AppendByte(FX_GETBYTEOFFSET24(offset)) < 0)
    388     return -1;
    389   if (pFile->AppendByte(FX_GETBYTEOFFSET16(offset)) < 0)
    390     return -1;
    391   if (pFile->AppendByte(FX_GETBYTEOFFSET8(offset)) < 0)
    392     return -1;
    393   if (pFile->AppendByte(FX_GETBYTEOFFSET0(offset)) < 0)
    394     return -1;
    395   if (pFile->AppendByte(0) < 0)
    396     return -1;
    397   return 0;
    398 }
    399 
    400 class CPDF_FlateEncoder {
    401  public:
    402   CPDF_FlateEncoder(CPDF_Stream* pStream, bool bFlateEncode);
    403   CPDF_FlateEncoder(const uint8_t* pBuffer,
    404                     uint32_t size,
    405                     bool bFlateEncode,
    406                     bool bXRefStream);
    407   ~CPDF_FlateEncoder();
    408 
    409   void CloneDict();
    410 
    411   uint32_t m_dwSize;
    412   CFX_MaybeOwned<uint8_t, FxFreeDeleter> m_pData;
    413   CFX_MaybeOwned<CPDF_Dictionary> m_pDict;
    414   CPDF_StreamAcc m_Acc;
    415 };
    416 
    417 void CPDF_FlateEncoder::CloneDict() {
    418   if (m_pDict.IsOwned())
    419     return;
    420   m_pDict = ToDictionary(m_pDict->Clone());
    421   ASSERT(m_pDict.IsOwned());
    422 }
    423 
    424 CPDF_FlateEncoder::CPDF_FlateEncoder(CPDF_Stream* pStream, bool bFlateEncode)
    425     : m_dwSize(0) {
    426   m_Acc.LoadAllData(pStream, true);
    427   bool bHasFilter = pStream && pStream->HasFilter();
    428   if (bHasFilter && !bFlateEncode) {
    429     CPDF_StreamAcc destAcc;
    430     destAcc.LoadAllData(pStream);
    431     m_dwSize = destAcc.GetSize();
    432     m_pData = destAcc.DetachData();
    433     m_pDict = ToDictionary(pStream->GetDict()->Clone());
    434     m_pDict->RemoveFor("Filter");
    435     return;
    436   }
    437   if (bHasFilter || !bFlateEncode) {
    438     m_pData = const_cast<uint8_t*>(m_Acc.GetData());
    439     m_dwSize = m_Acc.GetSize();
    440     m_pDict = pStream->GetDict();
    441     return;
    442   }
    443   // TODO(thestig): Move to Init() and check return value.
    444   uint8_t* buffer = nullptr;
    445   ::FlateEncode(m_Acc.GetData(), m_Acc.GetSize(), &buffer, &m_dwSize);
    446   m_pData = std::unique_ptr<uint8_t, FxFreeDeleter>(buffer);
    447   m_pDict = ToDictionary(pStream->GetDict()->Clone());
    448   m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(m_dwSize));
    449   m_pDict->SetNewFor<CPDF_Name>("Filter", "FlateDecode");
    450   m_pDict->RemoveFor("DecodeParms");
    451 }
    452 
    453 CPDF_FlateEncoder::CPDF_FlateEncoder(const uint8_t* pBuffer,
    454                                      uint32_t size,
    455                                      bool bFlateEncode,
    456                                      bool bXRefStream)
    457     : m_dwSize(0) {
    458   if (!bFlateEncode) {
    459     m_pData = const_cast<uint8_t*>(pBuffer);
    460     m_dwSize = size;
    461     return;
    462   }
    463   uint8_t* buffer = nullptr;
    464   // TODO(thestig): Move to Init() and check return value.
    465   if (bXRefStream)
    466     ::PngEncode(pBuffer, size, &buffer, &m_dwSize);
    467   else
    468     ::FlateEncode(pBuffer, size, &buffer, &m_dwSize);
    469   m_pData = std::unique_ptr<uint8_t, FxFreeDeleter>(buffer);
    470 }
    471 
    472 CPDF_FlateEncoder::~CPDF_FlateEncoder() {}
    473 
    474 class CPDF_Encryptor {
    475  public:
    476   CPDF_Encryptor(CPDF_CryptoHandler* pHandler,
    477                  int objnum,
    478                  uint8_t* src_data,
    479                  uint32_t src_size);
    480   ~CPDF_Encryptor();
    481 
    482   uint8_t* m_pData;
    483   uint32_t m_dwSize;
    484   bool m_bNewBuf;
    485 };
    486 
    487 CPDF_Encryptor::CPDF_Encryptor(CPDF_CryptoHandler* pHandler,
    488                                int objnum,
    489                                uint8_t* src_data,
    490                                uint32_t src_size)
    491     : m_pData(nullptr), m_dwSize(0), m_bNewBuf(false) {
    492   if (src_size == 0)
    493     return;
    494 
    495   if (!pHandler) {
    496     m_pData = (uint8_t*)src_data;
    497     m_dwSize = src_size;
    498     return;
    499   }
    500   m_dwSize = pHandler->EncryptGetSize(objnum, 0, src_data, src_size);
    501   m_pData = FX_Alloc(uint8_t, m_dwSize);
    502   pHandler->EncryptContent(objnum, 0, src_data, src_size, m_pData, m_dwSize);
    503   m_bNewBuf = true;
    504 }
    505 
    506 CPDF_Encryptor::~CPDF_Encryptor() {
    507   if (m_bNewBuf)
    508     FX_Free(m_pData);
    509 }
    510 
    511 }  // namespace
    512 
    513 CPDF_ObjectStream::CPDF_ObjectStream() : m_dwObjNum(0), m_index(0) {}
    514 
    515 CPDF_ObjectStream::~CPDF_ObjectStream() {}
    516 
    517 void CPDF_ObjectStream::Start() {
    518   m_Items.clear();
    519   m_Buffer.Clear();
    520   m_dwObjNum = 0;
    521   m_index = 0;
    522 }
    523 
    524 void CPDF_ObjectStream::CompressIndirectObject(uint32_t dwObjNum,
    525                                                const CPDF_Object* pObj) {
    526   m_Items.push_back({dwObjNum, m_Buffer.GetLength()});
    527   m_Buffer << pObj;
    528 }
    529 
    530 void CPDF_ObjectStream::CompressIndirectObject(uint32_t dwObjNum,
    531                                                const uint8_t* pBuffer,
    532                                                uint32_t dwSize) {
    533   m_Items.push_back({dwObjNum, m_Buffer.GetLength()});
    534   m_Buffer.AppendBlock(pBuffer, dwSize);
    535 }
    536 
    537 FX_FILESIZE CPDF_ObjectStream::End(CPDF_Creator* pCreator) {
    538   ASSERT(pCreator);
    539   if (m_Items.empty())
    540     return 0;
    541 
    542   CFX_FileBufferArchive* pFile = &pCreator->m_File;
    543   FX_FILESIZE ObjOffset = pCreator->m_Offset;
    544   if (!m_dwObjNum) {
    545     m_dwObjNum = ++pCreator->m_dwLastObjNum;
    546   }
    547   CFX_ByteTextBuf tempBuffer;
    548   for (const auto& pair : m_Items)
    549     tempBuffer << pair.objnum << " " << pair.offset << " ";
    550 
    551   FX_FILESIZE& offset = pCreator->m_Offset;
    552   int32_t len = pFile->AppendDWord(m_dwObjNum);
    553   if (len < 0) {
    554     return -1;
    555   }
    556   offset += len;
    557   if ((len = pFile->AppendString(" 0 obj\r\n<</Type /ObjStm /N ")) < 0) {
    558     return -1;
    559   }
    560   offset += len;
    561   uint32_t iCount = pdfium::CollectionSize<uint32_t>(m_Items);
    562   if ((len = pFile->AppendDWord(iCount)) < 0) {
    563     return -1;
    564   }
    565   offset += len;
    566   if (pFile->AppendString("/First ") < 0) {
    567     return -1;
    568   }
    569   if ((len = pFile->AppendDWord((uint32_t)tempBuffer.GetLength())) < 0) {
    570     return -1;
    571   }
    572   if (pFile->AppendString("/Length ") < 0) {
    573     return -1;
    574   }
    575   offset += len + 15;
    576 
    577   tempBuffer << m_Buffer;
    578   CPDF_FlateEncoder encoder(tempBuffer.GetBuffer(), tempBuffer.GetLength(),
    579                             true, false);
    580   CPDF_Encryptor encryptor(pCreator->m_pCryptoHandler, m_dwObjNum,
    581                            encoder.m_pData.Get(), encoder.m_dwSize);
    582   if ((len = pFile->AppendDWord(encryptor.m_dwSize)) < 0) {
    583     return -1;
    584   }
    585   offset += len;
    586   if (pFile->AppendString("/Filter /FlateDecode") < 0) {
    587     return -1;
    588   }
    589   offset += 20;
    590   if ((len = pFile->AppendString(">>stream\r\n")) < 0) {
    591     return -1;
    592   }
    593   if (pFile->AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0) {
    594     return -1;
    595   }
    596   offset += len + encryptor.m_dwSize;
    597   if ((len = pFile->AppendString("\r\nendstream\r\nendobj\r\n")) < 0) {
    598     return -1;
    599   }
    600   offset += len;
    601   return ObjOffset;
    602 }
    603 
    604 CPDF_XRefStream::CPDF_XRefStream()
    605     : m_PrevOffset(0), m_dwTempObjNum(0), m_iSeg(0) {}
    606 
    607 CPDF_XRefStream::~CPDF_XRefStream() {}
    608 
    609 bool CPDF_XRefStream::Start() {
    610   m_IndexArray.clear();
    611   m_Buffer.Clear();
    612   m_iSeg = 0;
    613   return true;
    614 }
    615 int32_t CPDF_XRefStream::CompressIndirectObject(uint32_t dwObjNum,
    616                                                 const CPDF_Object* pObj,
    617                                                 CPDF_Creator* pCreator) {
    618   if (!pCreator)
    619     return 0;
    620 
    621   m_ObjStream.CompressIndirectObject(dwObjNum, pObj);
    622   if (pdfium::CollectionSize<int32_t>(m_ObjStream.m_Items) <
    623           pCreator->m_ObjectStreamSize &&
    624       m_ObjStream.m_Buffer.GetLength() < PDF_OBJECTSTREAM_MAXLENGTH) {
    625     return 1;
    626   }
    627   return EndObjectStream(pCreator);
    628 }
    629 int32_t CPDF_XRefStream::CompressIndirectObject(uint32_t dwObjNum,
    630                                                 const uint8_t* pBuffer,
    631                                                 uint32_t dwSize,
    632                                                 CPDF_Creator* pCreator) {
    633   if (!pCreator)
    634     return 0;
    635 
    636   m_ObjStream.CompressIndirectObject(dwObjNum, pBuffer, dwSize);
    637   if (pdfium::CollectionSize<int32_t>(m_ObjStream.m_Items) <
    638           pCreator->m_ObjectStreamSize &&
    639       m_ObjStream.m_Buffer.GetLength() < PDF_OBJECTSTREAM_MAXLENGTH) {
    640     return 1;
    641   }
    642   return EndObjectStream(pCreator);
    643 }
    644 
    645 int32_t CPDF_XRefStream::EndObjectStream(CPDF_Creator* pCreator, bool bEOF) {
    646   FX_FILESIZE objOffset = 0;
    647   if (bEOF) {
    648     objOffset = m_ObjStream.End(pCreator);
    649     if (objOffset < 0) {
    650       return -1;
    651     }
    652   }
    653   uint32_t& dwObjStmNum = m_ObjStream.m_dwObjNum;
    654   if (!dwObjStmNum) {
    655     dwObjStmNum = ++pCreator->m_dwLastObjNum;
    656   }
    657   int32_t iSize = pdfium::CollectionSize<int32_t>(m_ObjStream.m_Items);
    658   size_t iSeg = m_IndexArray.size();
    659   if (!(pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL)) {
    660     if (m_dwTempObjNum == 0) {
    661       AppendIndex0(m_Buffer, true);
    662       m_dwTempObjNum++;
    663     }
    664     uint32_t end_num = m_IndexArray.back().objnum + m_IndexArray.back().count;
    665     int index = 0;
    666     for (; m_dwTempObjNum < end_num; m_dwTempObjNum++) {
    667       FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(m_dwTempObjNum);
    668       if (offset) {
    669         if (index >= iSize ||
    670             m_dwTempObjNum != m_ObjStream.m_Items[index].objnum) {
    671           AppendIndex1(m_Buffer, *offset);
    672         } else {
    673           AppendIndex2(m_Buffer, dwObjStmNum, index++);
    674         }
    675       } else {
    676         AppendIndex0(m_Buffer, false);
    677       }
    678     }
    679     if (iSize > 0 && bEOF) {
    680       pCreator->m_ObjectOffset.Add(dwObjStmNum, 1);
    681       pCreator->m_ObjectOffset[dwObjStmNum] = objOffset;
    682     }
    683     m_iSeg = iSeg;
    684     if (bEOF) {
    685       m_ObjStream.Start();
    686     }
    687     return 1;
    688   }
    689   for (auto it = m_IndexArray.begin() + m_iSeg; it != m_IndexArray.end();
    690        ++it) {
    691     for (uint32_t m = it->objnum; m < it->objnum + it->count; ++m) {
    692       if (m_ObjStream.m_index >= iSize ||
    693           m != m_ObjStream.m_Items[it - m_IndexArray.begin()].objnum) {
    694         AppendIndex1(m_Buffer, pCreator->m_ObjectOffset[m]);
    695       } else {
    696         AppendIndex2(m_Buffer, dwObjStmNum, m_ObjStream.m_index++);
    697       }
    698     }
    699   }
    700   if (iSize > 0 && bEOF) {
    701     AppendIndex1(m_Buffer, objOffset);
    702     m_IndexArray.push_back({dwObjStmNum, 1});
    703     iSeg += 1;
    704   }
    705   m_iSeg = iSeg;
    706   if (bEOF) {
    707     m_ObjStream.Start();
    708   }
    709   return 1;
    710 }
    711 bool CPDF_XRefStream::GenerateXRefStream(CPDF_Creator* pCreator, bool bEOF) {
    712   FX_FILESIZE offset_tmp = pCreator->m_Offset;
    713   uint32_t objnum = ++pCreator->m_dwLastObjNum;
    714   CFX_FileBufferArchive* pFile = &pCreator->m_File;
    715   bool bIncremental = (pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL) != 0;
    716   if (bIncremental) {
    717     AddObjectNumberToIndexArray(objnum);
    718   } else {
    719     for (; m_dwTempObjNum < pCreator->m_dwLastObjNum; m_dwTempObjNum++) {
    720       FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(m_dwTempObjNum);
    721       if (offset) {
    722         AppendIndex1(m_Buffer, *offset);
    723       } else {
    724         AppendIndex0(m_Buffer, false);
    725       }
    726     }
    727   }
    728   AppendIndex1(m_Buffer, offset_tmp);
    729   FX_FILESIZE& offset = pCreator->m_Offset;
    730   int32_t len = pFile->AppendDWord(objnum);
    731   if (len < 0) {
    732     return false;
    733   }
    734   offset += len;
    735   if ((len = pFile->AppendString(" 0 obj\r\n<</Type /XRef/W[1 4 2]/Index[")) <
    736       0) {
    737     return false;
    738   }
    739   offset += len;
    740   if (!bIncremental) {
    741     if ((len = pFile->AppendDWord(0)) < 0) {
    742       return false;
    743     }
    744     if ((len = pFile->AppendString(" ")) < 0) {
    745       return false;
    746     }
    747     offset += len + 1;
    748     if ((len = pFile->AppendDWord(objnum + 1)) < 0) {
    749       return false;
    750     }
    751     offset += len;
    752   } else {
    753     for (const auto& pair : m_IndexArray) {
    754       if ((len = pFile->AppendDWord(pair.objnum)) < 0) {
    755         return false;
    756       }
    757       if (pFile->AppendString(" ") < 0) {
    758         return false;
    759       }
    760       offset += len + 1;
    761       if ((len = pFile->AppendDWord(pair.count)) < 0) {
    762         return false;
    763       }
    764       if (pFile->AppendString(" ") < 0) {
    765         return false;
    766       }
    767       offset += len + 1;
    768     }
    769   }
    770   if (pFile->AppendString("]/Size ") < 0) {
    771     return false;
    772   }
    773   if ((len = pFile->AppendDWord(objnum + 1)) < 0) {
    774     return false;
    775   }
    776   offset += len + 7;
    777   if (m_PrevOffset > 0) {
    778     if (pFile->AppendString("/Prev ") < 0) {
    779       return false;
    780     }
    781     FX_CHAR offset_buf[20];
    782     FXSYS_memset(offset_buf, 0, sizeof(offset_buf));
    783     FXSYS_i64toa(m_PrevOffset, offset_buf, 10);
    784     int32_t offset_len = (int32_t)FXSYS_strlen(offset_buf);
    785     if (pFile->AppendBlock(offset_buf, offset_len) < 0) {
    786       return false;
    787     }
    788     offset += offset_len + 6;
    789   }
    790   CPDF_FlateEncoder encoder(m_Buffer.GetBuffer(), m_Buffer.GetLength(), true,
    791                             true);
    792   if (pFile->AppendString("/Filter /FlateDecode") < 0)
    793     return false;
    794 
    795   offset += 20;
    796   if ((len = pFile->AppendString("/DecodeParms<</Columns 7/Predictor 12>>")) <
    797       0) {
    798     return false;
    799   }
    800 
    801   offset += len;
    802   if (pFile->AppendString("/Length ") < 0)
    803     return false;
    804 
    805   if ((len = pFile->AppendDWord(encoder.m_dwSize)) < 0)
    806     return false;
    807 
    808   offset += len + 8;
    809   if (bEOF) {
    810     if ((len = PDF_CreatorWriteTrailer(pCreator->m_pDocument, pFile,
    811                                        pCreator->m_pIDArray.get())) < 0) {
    812       return false;
    813     }
    814     offset += len;
    815     if (pCreator->m_pEncryptDict) {
    816       uint32_t dwEncryptObjNum = pCreator->m_pEncryptDict->GetObjNum();
    817       if (dwEncryptObjNum == 0) {
    818         dwEncryptObjNum = pCreator->m_dwEncryptObjNum;
    819       }
    820       if ((len = PDF_CreatorWriteEncrypt(pCreator->m_pEncryptDict,
    821                                          dwEncryptObjNum, pFile)) < 0) {
    822         return false;
    823       }
    824       offset += len;
    825     }
    826   }
    827   if ((len = pFile->AppendString(">>stream\r\n")) < 0)
    828     return false;
    829 
    830   offset += len;
    831   if (pFile->AppendBlock(encoder.m_pData.Get(), encoder.m_dwSize) < 0)
    832     return false;
    833 
    834   if ((len = pFile->AppendString("\r\nendstream\r\nendobj\r\n")) < 0)
    835     return false;
    836 
    837   offset += encoder.m_dwSize + len;
    838   m_PrevOffset = offset_tmp;
    839   return true;
    840 }
    841 
    842 bool CPDF_XRefStream::End(CPDF_Creator* pCreator, bool bEOF) {
    843   if (EndObjectStream(pCreator, bEOF) < 0) {
    844     return false;
    845   }
    846   return GenerateXRefStream(pCreator, bEOF);
    847 }
    848 bool CPDF_XRefStream::EndXRefStream(CPDF_Creator* pCreator) {
    849   if (!(pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL)) {
    850     AppendIndex0(m_Buffer, true);
    851     for (uint32_t i = 1; i < pCreator->m_dwLastObjNum + 1; i++) {
    852       FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(i);
    853       if (offset) {
    854         AppendIndex1(m_Buffer, *offset);
    855       } else {
    856         AppendIndex0(m_Buffer, false);
    857       }
    858     }
    859   } else {
    860     for (const auto& pair : m_IndexArray) {
    861       for (uint32_t j = pair.objnum; j < pair.objnum + pair.count; ++j)
    862         AppendIndex1(m_Buffer, pCreator->m_ObjectOffset[j]);
    863     }
    864   }
    865   return GenerateXRefStream(pCreator, false);
    866 }
    867 void CPDF_XRefStream::AddObjectNumberToIndexArray(uint32_t objnum) {
    868   if (m_IndexArray.empty()) {
    869     m_IndexArray.push_back({objnum, 1});
    870     return;
    871   }
    872   uint32_t next_objnum = m_IndexArray.back().objnum + m_IndexArray.back().count;
    873   if (objnum == next_objnum)
    874     m_IndexArray.back().count += 1;
    875   else
    876     m_IndexArray.push_back({objnum, 1});
    877 }
    878 
    879 CPDF_Creator::CPDF_Creator(CPDF_Document* pDoc)
    880     : m_pDocument(pDoc),
    881       m_pParser(pDoc->GetParser()),
    882       m_bSecurityChanged(false),
    883       m_pEncryptDict(m_pParser ? m_pParser->GetEncryptDict() : nullptr),
    884       m_dwEncryptObjNum(0),
    885       m_bEncryptCloned(false),
    886       m_pCryptoHandler(m_pParser ? m_pParser->GetCryptoHandler() : nullptr),
    887       m_bLocalCryptoHandler(false),
    888       m_pMetadata(nullptr),
    889       m_ObjectStreamSize(200),
    890       m_dwLastObjNum(m_pDocument->GetLastObjNum()),
    891       m_Offset(0),
    892       m_iStage(-1),
    893       m_dwFlags(0),
    894       m_Pos(nullptr),
    895       m_XrefStart(0),
    896       m_pIDArray(nullptr),
    897       m_FileVersion(0) {}
    898 
    899 CPDF_Creator::~CPDF_Creator() {
    900   ResetStandardSecurity();
    901   if (m_bEncryptCloned) {
    902     delete m_pEncryptDict;
    903     m_pEncryptDict = nullptr;
    904   }
    905   Clear();
    906 }
    907 
    908 int32_t CPDF_Creator::WriteIndirectObjectToStream(const CPDF_Object* pObj) {
    909   if (!m_pXRefStream)
    910     return 1;
    911 
    912   uint32_t objnum = pObj->GetObjNum();
    913   if (m_pParser && m_pParser->GetObjectGenNum(objnum) > 0)
    914     return 1;
    915 
    916   if (pObj->IsNumber())
    917     return 1;
    918 
    919   CPDF_Dictionary* pDict = pObj->GetDict();
    920   if (pObj->IsStream()) {
    921     if (pDict && pDict->GetStringFor("Type") == "XRef")
    922       return 0;
    923     return 1;
    924   }
    925 
    926   if (pDict) {
    927     if (pDict == m_pDocument->GetRoot() || pDict == m_pEncryptDict)
    928       return 1;
    929     if (pDict->IsSignatureDict())
    930       return 1;
    931     if (pDict->GetStringFor("Type") == "Page")
    932       return 1;
    933   }
    934 
    935   m_pXRefStream->AddObjectNumberToIndexArray(objnum);
    936   if (m_pXRefStream->CompressIndirectObject(objnum, pObj, this) < 0)
    937     return -1;
    938   if (!IsXRefNeedEnd(m_pXRefStream.get(), m_dwFlags))
    939     return 0;
    940   if (!m_pXRefStream->End(this))
    941     return -1;
    942   if (!m_pXRefStream->Start())
    943     return -1;
    944   return 0;
    945 }
    946 int32_t CPDF_Creator::WriteIndirectObjectToStream(uint32_t objnum,
    947                                                   const uint8_t* pBuffer,
    948                                                   uint32_t dwSize) {
    949   if (!m_pXRefStream) {
    950     return 1;
    951   }
    952   m_pXRefStream->AddObjectNumberToIndexArray(objnum);
    953   int32_t iRet =
    954       m_pXRefStream->CompressIndirectObject(objnum, pBuffer, dwSize, this);
    955   if (iRet < 1) {
    956     return iRet;
    957   }
    958   if (!IsXRefNeedEnd(m_pXRefStream.get(), m_dwFlags)) {
    959     return 0;
    960   }
    961   if (!m_pXRefStream->End(this)) {
    962     return -1;
    963   }
    964   if (!m_pXRefStream->Start()) {
    965     return -1;
    966   }
    967   return 0;
    968 }
    969 int32_t CPDF_Creator::AppendObjectNumberToXRef(uint32_t objnum) {
    970   if (!m_pXRefStream) {
    971     return 1;
    972   }
    973   m_pXRefStream->AddObjectNumberToIndexArray(objnum);
    974   if (!IsXRefNeedEnd(m_pXRefStream.get(), m_dwFlags)) {
    975     return 0;
    976   }
    977   if (!m_pXRefStream->End(this)) {
    978     return -1;
    979   }
    980   if (!m_pXRefStream->Start()) {
    981     return -1;
    982   }
    983   return 0;
    984 }
    985 int32_t CPDF_Creator::WriteStream(const CPDF_Object* pStream,
    986                                   uint32_t objnum,
    987                                   CPDF_CryptoHandler* pCrypto) {
    988   CPDF_FlateEncoder encoder(const_cast<CPDF_Stream*>(pStream->AsStream()),
    989                             pStream != m_pMetadata);
    990   CPDF_Encryptor encryptor(pCrypto, objnum, encoder.m_pData.Get(),
    991                            encoder.m_dwSize);
    992   if (static_cast<uint32_t>(encoder.m_pDict->GetIntegerFor("Length")) !=
    993       encryptor.m_dwSize) {
    994     encoder.CloneDict();
    995     encoder.m_pDict->SetNewFor<CPDF_Number>(
    996         "Length", static_cast<int>(encryptor.m_dwSize));
    997   }
    998   if (WriteDirectObj(objnum, encoder.m_pDict.Get()) < 0)
    999     return -1;
   1000 
   1001   int len = m_File.AppendString("stream\r\n");
   1002   if (len < 0)
   1003     return -1;
   1004 
   1005   m_Offset += len;
   1006   if (m_File.AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0)
   1007     return -1;
   1008 
   1009   m_Offset += encryptor.m_dwSize;
   1010   if ((len = m_File.AppendString("\r\nendstream")) < 0)
   1011     return -1;
   1012 
   1013   m_Offset += len;
   1014   return 1;
   1015 }
   1016 int32_t CPDF_Creator::WriteIndirectObj(uint32_t objnum,
   1017                                        const CPDF_Object* pObj) {
   1018   int32_t len = m_File.AppendDWord(objnum);
   1019   if (len < 0)
   1020     return -1;
   1021 
   1022   m_Offset += len;
   1023   if ((len = m_File.AppendString(" 0 obj\r\n")) < 0)
   1024     return -1;
   1025 
   1026   m_Offset += len;
   1027   if (pObj->IsStream()) {
   1028     CPDF_CryptoHandler* pHandler =
   1029         pObj != m_pMetadata ? m_pCryptoHandler : nullptr;
   1030     if (WriteStream(pObj, objnum, pHandler) < 0)
   1031       return -1;
   1032   } else {
   1033     if (WriteDirectObj(objnum, pObj) < 0)
   1034       return -1;
   1035   }
   1036   if ((len = m_File.AppendString("\r\nendobj\r\n")) < 0)
   1037     return -1;
   1038 
   1039   m_Offset += len;
   1040   if (AppendObjectNumberToXRef(objnum) < 0)
   1041     return -1;
   1042   return 0;
   1043 }
   1044 int32_t CPDF_Creator::WriteIndirectObj(const CPDF_Object* pObj) {
   1045   int32_t iRet = WriteIndirectObjectToStream(pObj);
   1046   if (iRet < 1) {
   1047     return iRet;
   1048   }
   1049   return WriteIndirectObj(pObj->GetObjNum(), pObj);
   1050 }
   1051 int32_t CPDF_Creator::WriteDirectObj(uint32_t objnum,
   1052                                      const CPDF_Object* pObj,
   1053                                      bool bEncrypt) {
   1054   int32_t len = 0;
   1055   if (!pObj) {
   1056     if (m_File.AppendString(" null") < 0) {
   1057       return -1;
   1058     }
   1059     m_Offset += 5;
   1060     return 1;
   1061   }
   1062   switch (pObj->GetType()) {
   1063     case CPDF_Object::NULLOBJ:
   1064       if (m_File.AppendString(" null") < 0) {
   1065         return -1;
   1066       }
   1067       m_Offset += 5;
   1068       break;
   1069     case CPDF_Object::BOOLEAN:
   1070     case CPDF_Object::NUMBER:
   1071       if (m_File.AppendString(" ") < 0) {
   1072         return -1;
   1073       }
   1074       if ((len = m_File.AppendString(pObj->GetString().AsStringC())) < 0) {
   1075         return -1;
   1076       }
   1077       m_Offset += len + 1;
   1078       break;
   1079     case CPDF_Object::STRING: {
   1080       CFX_ByteString str = pObj->GetString();
   1081       bool bHex = pObj->AsString()->IsHex();
   1082       if (!m_pCryptoHandler || !bEncrypt) {
   1083         CFX_ByteString content = PDF_EncodeString(str, bHex);
   1084         if ((len = m_File.AppendString(content.AsStringC())) < 0) {
   1085           return -1;
   1086         }
   1087         m_Offset += len;
   1088         break;
   1089       }
   1090       CPDF_Encryptor encryptor(m_pCryptoHandler, objnum, (uint8_t*)str.c_str(),
   1091                                str.GetLength());
   1092       CFX_ByteString content = PDF_EncodeString(
   1093           CFX_ByteString((const FX_CHAR*)encryptor.m_pData, encryptor.m_dwSize),
   1094           bHex);
   1095       if ((len = m_File.AppendString(content.AsStringC())) < 0) {
   1096         return -1;
   1097       }
   1098       m_Offset += len;
   1099       break;
   1100     }
   1101     case CPDF_Object::STREAM: {
   1102       CPDF_FlateEncoder encoder(const_cast<CPDF_Stream*>(pObj->AsStream()),
   1103                                 true);
   1104       CPDF_Encryptor encryptor(m_pCryptoHandler, objnum, encoder.m_pData.Get(),
   1105                                encoder.m_dwSize);
   1106       if (static_cast<uint32_t>(encoder.m_pDict->GetIntegerFor("Length")) !=
   1107           encryptor.m_dwSize) {
   1108         encoder.CloneDict();
   1109         encoder.m_pDict->SetNewFor<CPDF_Number>(
   1110             "Length", static_cast<int>(encryptor.m_dwSize));
   1111       }
   1112       if (WriteDirectObj(objnum, encoder.m_pDict.Get()) < 0)
   1113         return -1;
   1114 
   1115       if ((len = m_File.AppendString("stream\r\n")) < 0)
   1116         return -1;
   1117 
   1118       m_Offset += len;
   1119       if (m_File.AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0)
   1120         return -1;
   1121 
   1122       m_Offset += encryptor.m_dwSize;
   1123       if ((len = m_File.AppendString("\r\nendstream")) < 0)
   1124         return -1;
   1125 
   1126       m_Offset += len;
   1127       break;
   1128     }
   1129     case CPDF_Object::NAME: {
   1130       if (m_File.AppendString("/") < 0) {
   1131         return -1;
   1132       }
   1133       CFX_ByteString str = pObj->GetString();
   1134       if ((len = m_File.AppendString(PDF_NameEncode(str).AsStringC())) < 0) {
   1135         return -1;
   1136       }
   1137       m_Offset += len + 1;
   1138       break;
   1139     }
   1140     case CPDF_Object::REFERENCE: {
   1141       if (m_File.AppendString(" ") < 0)
   1142         return -1;
   1143       if ((len = m_File.AppendDWord(pObj->AsReference()->GetRefObjNum())) < 0)
   1144         return -1;
   1145       if (m_File.AppendString(" 0 R") < 0)
   1146         return -1;
   1147       m_Offset += len + 5;
   1148       break;
   1149     }
   1150     case CPDF_Object::ARRAY: {
   1151       if (m_File.AppendString("[") < 0) {
   1152         return -1;
   1153       }
   1154       m_Offset += 1;
   1155       const CPDF_Array* p = pObj->AsArray();
   1156       for (size_t i = 0; i < p->GetCount(); i++) {
   1157         CPDF_Object* pElement = p->GetObjectAt(i);
   1158         if (!pElement->IsInline()) {
   1159           if (m_File.AppendString(" ") < 0) {
   1160             return -1;
   1161           }
   1162           if ((len = m_File.AppendDWord(pElement->GetObjNum())) < 0) {
   1163             return -1;
   1164           }
   1165           if (m_File.AppendString(" 0 R") < 0) {
   1166             return -1;
   1167           }
   1168           m_Offset += len + 5;
   1169         } else {
   1170           if (WriteDirectObj(objnum, pElement) < 0) {
   1171             return -1;
   1172           }
   1173         }
   1174       }
   1175       if (m_File.AppendString("]") < 0) {
   1176         return -1;
   1177       }
   1178       m_Offset += 1;
   1179       break;
   1180     }
   1181     case CPDF_Object::DICTIONARY: {
   1182       if (!m_pCryptoHandler || pObj == m_pEncryptDict)
   1183         return PDF_CreatorAppendObject(pObj, &m_File, m_Offset);
   1184       if (m_File.AppendString("<<") < 0)
   1185         return -1;
   1186 
   1187       m_Offset += 2;
   1188       const CPDF_Dictionary* p = pObj->AsDictionary();
   1189       bool bSignDict = p->IsSignatureDict();
   1190       for (const auto& it : *p) {
   1191         bool bSignValue = false;
   1192         const CFX_ByteString& key = it.first;
   1193         CPDF_Object* pValue = it.second.get();
   1194         if (m_File.AppendString("/") < 0) {
   1195           return -1;
   1196         }
   1197         if ((len = m_File.AppendString(PDF_NameEncode(key).AsStringC())) < 0) {
   1198           return -1;
   1199         }
   1200         m_Offset += len + 1;
   1201         if (bSignDict && key == "Contents") {
   1202           bSignValue = true;
   1203         }
   1204         if (!pValue->IsInline()) {
   1205           if (m_File.AppendString(" ") < 0) {
   1206             return -1;
   1207           }
   1208           if ((len = m_File.AppendDWord(pValue->GetObjNum())) < 0) {
   1209             return -1;
   1210           }
   1211           if (m_File.AppendString(" 0 R ") < 0) {
   1212             return -1;
   1213           }
   1214           m_Offset += len + 6;
   1215         } else {
   1216           if (WriteDirectObj(objnum, pValue, !bSignValue) < 0) {
   1217             return -1;
   1218           }
   1219         }
   1220       }
   1221       if (m_File.AppendString(">>") < 0) {
   1222         return -1;
   1223       }
   1224       m_Offset += 2;
   1225       break;
   1226     }
   1227   }
   1228   return 1;
   1229 }
   1230 int32_t CPDF_Creator::WriteOldIndirectObject(uint32_t objnum) {
   1231   if (m_pParser->IsObjectFreeOrNull(objnum))
   1232     return 0;
   1233 
   1234   m_ObjectOffset[objnum] = m_Offset;
   1235   bool bExistInMap = !!m_pDocument->GetIndirectObject(objnum);
   1236   const uint8_t object_type = m_pParser->GetObjectType(objnum);
   1237   bool bObjStm = (object_type == 2) && m_pEncryptDict && !m_pXRefStream;
   1238   if (m_pParser->IsVersionUpdated() || m_bSecurityChanged || bExistInMap ||
   1239       bObjStm) {
   1240     CPDF_Object* pObj = m_pDocument->GetOrParseIndirectObject(objnum);
   1241     if (!pObj) {
   1242       m_ObjectOffset[objnum] = 0;
   1243       return 0;
   1244     }
   1245     if (WriteIndirectObj(pObj)) {
   1246       return -1;
   1247     }
   1248     if (!bExistInMap) {
   1249       m_pDocument->DeleteIndirectObject(objnum);
   1250     }
   1251   } else {
   1252     uint8_t* pBuffer;
   1253     uint32_t size;
   1254     m_pParser->GetIndirectBinary(objnum, pBuffer, size);
   1255     if (!pBuffer) {
   1256       return 0;
   1257     }
   1258     if (object_type == 2) {
   1259       if (m_pXRefStream) {
   1260         if (WriteIndirectObjectToStream(objnum, pBuffer, size) < 0) {
   1261           FX_Free(pBuffer);
   1262           return -1;
   1263         }
   1264       } else {
   1265         int32_t len = m_File.AppendDWord(objnum);
   1266         if (len < 0) {
   1267           return -1;
   1268         }
   1269         if (m_File.AppendString(" 0 obj ") < 0) {
   1270           return -1;
   1271         }
   1272         m_Offset += len + 7;
   1273         if (m_File.AppendBlock(pBuffer, size) < 0) {
   1274           return -1;
   1275         }
   1276         m_Offset += size;
   1277         if (m_File.AppendString("\r\nendobj\r\n") < 0) {
   1278           return -1;
   1279         }
   1280         m_Offset += 10;
   1281       }
   1282     } else {
   1283       if (m_File.AppendBlock(pBuffer, size) < 0) {
   1284         return -1;
   1285       }
   1286       m_Offset += size;
   1287       if (AppendObjectNumberToXRef(objnum) < 0) {
   1288         return -1;
   1289       }
   1290     }
   1291     FX_Free(pBuffer);
   1292   }
   1293   return 1;
   1294 }
   1295 int32_t CPDF_Creator::WriteOldObjs(IFX_Pause* pPause) {
   1296   uint32_t nLastObjNum = m_pParser->GetLastObjNum();
   1297   if (!m_pParser->IsValidObjectNumber(nLastObjNum))
   1298     return 0;
   1299 
   1300   uint32_t objnum = (uint32_t)(uintptr_t)m_Pos;
   1301   for (; objnum <= nLastObjNum; ++objnum) {
   1302     int32_t iRet = WriteOldIndirectObject(objnum);
   1303     if (iRet < 0)
   1304       return iRet;
   1305 
   1306     if (!iRet)
   1307       continue;
   1308 
   1309     if (pPause && pPause->NeedToPauseNow()) {
   1310       m_Pos = (void*)(uintptr_t)(objnum + 1);
   1311       return 1;
   1312     }
   1313   }
   1314   return 0;
   1315 }
   1316 
   1317 int32_t CPDF_Creator::WriteNewObjs(bool bIncremental, IFX_Pause* pPause) {
   1318   size_t iCount = m_NewObjNumArray.size();
   1319   size_t index = (size_t)(uintptr_t)m_Pos;
   1320   while (index < iCount) {
   1321     uint32_t objnum = m_NewObjNumArray[index];
   1322     CPDF_Object* pObj = m_pDocument->GetIndirectObject(objnum);
   1323     if (!pObj) {
   1324       ++index;
   1325       continue;
   1326     }
   1327     m_ObjectOffset[objnum] = m_Offset;
   1328     if (WriteIndirectObj(pObj))
   1329       return -1;
   1330 
   1331     index++;
   1332     if (pPause && pPause->NeedToPauseNow()) {
   1333       m_Pos = (FX_POSITION)(uintptr_t)index;
   1334       return 1;
   1335     }
   1336   }
   1337   return 0;
   1338 }
   1339 
   1340 void CPDF_Creator::InitOldObjNumOffsets() {
   1341   if (!m_pParser) {
   1342     return;
   1343   }
   1344   uint32_t j = 0;
   1345   uint32_t dwStart = 0;
   1346   uint32_t dwEnd = m_pParser->GetLastObjNum();
   1347   while (dwStart <= dwEnd) {
   1348     while (dwStart <= dwEnd && m_pParser->IsObjectFreeOrNull(dwStart))
   1349       dwStart++;
   1350 
   1351     if (dwStart > dwEnd)
   1352       break;
   1353 
   1354     j = dwStart;
   1355     while (j <= dwEnd && !m_pParser->IsObjectFreeOrNull(j))
   1356       j++;
   1357 
   1358     m_ObjectOffset.Add(dwStart, j - dwStart);
   1359     dwStart = j;
   1360   }
   1361 }
   1362 
   1363 void CPDF_Creator::InitNewObjNumOffsets() {
   1364   bool bIncremental = (m_dwFlags & FPDFCREATE_INCREMENTAL) != 0;
   1365   bool bNoOriginal = (m_dwFlags & FPDFCREATE_NO_ORIGINAL) != 0;
   1366   for (const auto& pair : *m_pDocument) {
   1367     const uint32_t objnum = pair.first;
   1368     const CPDF_Object* pObj = pair.second.get();
   1369     if (bIncremental || pObj->GetObjNum() == CPDF_Object::kInvalidObjNum)
   1370       continue;
   1371     if (m_pParser && m_pParser->IsValidObjectNumber(objnum) &&
   1372         m_pParser->GetObjectType(objnum)) {
   1373       continue;
   1374     }
   1375     AppendNewObjNum(objnum);
   1376   }
   1377 
   1378   size_t iCount = m_NewObjNumArray.size();
   1379   if (iCount == 0)
   1380     return;
   1381 
   1382   size_t i = 0;
   1383   uint32_t dwStartObjNum = 0;
   1384   bool bCrossRefValid = m_pParser && m_pParser->GetLastXRefOffset() > 0;
   1385   while (i < iCount) {
   1386     dwStartObjNum = m_NewObjNumArray[i];
   1387     if ((bIncremental && (bNoOriginal || bCrossRefValid)) ||
   1388         !m_ObjectOffset.GetPtrAt(dwStartObjNum)) {
   1389       break;
   1390     }
   1391     i++;
   1392   }
   1393   if (i >= iCount)
   1394     return;
   1395 
   1396   uint32_t dwLastObjNum = dwStartObjNum;
   1397   i++;
   1398   bool bNewStart = false;
   1399   for (; i < iCount; i++) {
   1400     uint32_t dwCurObjNum = m_NewObjNumArray[i];
   1401     bool bExist = m_pParser && m_pParser->IsValidObjectNumber(dwCurObjNum) &&
   1402                   m_ObjectOffset.GetPtrAt(dwCurObjNum);
   1403     if (bExist || dwCurObjNum - dwLastObjNum > 1) {
   1404       if (!bNewStart)
   1405         m_ObjectOffset.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);
   1406       dwStartObjNum = dwCurObjNum;
   1407     }
   1408     if (bNewStart)
   1409       dwStartObjNum = dwCurObjNum;
   1410 
   1411     bNewStart = bExist;
   1412     dwLastObjNum = dwCurObjNum;
   1413   }
   1414   m_ObjectOffset.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);
   1415 }
   1416 
   1417 void CPDF_Creator::AppendNewObjNum(uint32_t objnum) {
   1418   m_NewObjNumArray.insert(std::lower_bound(m_NewObjNumArray.begin(),
   1419                                            m_NewObjNumArray.end(), objnum),
   1420                           objnum);
   1421 }
   1422 
   1423 int32_t CPDF_Creator::WriteDoc_Stage1(IFX_Pause* pPause) {
   1424   ASSERT(m_iStage > -1 || m_iStage < 20);
   1425   if (m_iStage == 0) {
   1426     if (!m_pParser) {
   1427       m_dwFlags &= ~FPDFCREATE_INCREMENTAL;
   1428     }
   1429     if (m_bSecurityChanged && (m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0) {
   1430       m_dwFlags &= ~FPDFCREATE_INCREMENTAL;
   1431     }
   1432     CPDF_Dictionary* pDict = m_pDocument->GetRoot();
   1433     m_pMetadata = pDict ? pDict->GetDirectObjectFor("Metadata") : nullptr;
   1434     if (m_dwFlags & FPDFCREATE_OBJECTSTREAM) {
   1435       m_pXRefStream = pdfium::MakeUnique<CPDF_XRefStream>();
   1436       m_pXRefStream->Start();
   1437       if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser) {
   1438         FX_FILESIZE prev = m_pParser->GetLastXRefOffset();
   1439         m_pXRefStream->m_PrevOffset = prev;
   1440       }
   1441     }
   1442     m_iStage = 10;
   1443   }
   1444   if (m_iStage == 10) {
   1445     if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0) {
   1446       if (m_File.AppendString("%PDF-1.") < 0) {
   1447         return -1;
   1448       }
   1449       m_Offset += 7;
   1450       int32_t version = 7;
   1451       if (m_FileVersion) {
   1452         version = m_FileVersion;
   1453       } else if (m_pParser) {
   1454         version = m_pParser->GetFileVersion();
   1455       }
   1456       int32_t len = m_File.AppendDWord(version % 10);
   1457       if (len < 0) {
   1458         return -1;
   1459       }
   1460       m_Offset += len;
   1461       if ((len = m_File.AppendString("\r\n%\xA1\xB3\xC5\xD7\r\n")) < 0) {
   1462         return -1;
   1463       }
   1464       m_Offset += len;
   1465       InitOldObjNumOffsets();
   1466       m_iStage = 20;
   1467     } else {
   1468       CFX_RetainPtr<IFX_SeekableReadStream> pSrcFile =
   1469           m_pParser->GetFileAccess();
   1470       m_Offset = pSrcFile->GetSize();
   1471       m_Pos = (void*)(uintptr_t)m_Offset;
   1472       m_iStage = 15;
   1473     }
   1474   }
   1475   if (m_iStage == 15) {
   1476     if ((m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0 && m_Pos) {
   1477       CFX_RetainPtr<IFX_SeekableReadStream> pSrcFile =
   1478           m_pParser->GetFileAccess();
   1479       uint8_t buffer[4096];  // TODO(tsepez): don't stack allocate.
   1480       uint32_t src_size = (uint32_t)(uintptr_t)m_Pos;
   1481       while (src_size) {
   1482         uint32_t block_size = src_size > 4096 ? 4096 : src_size;
   1483         if (!pSrcFile->ReadBlock(buffer, m_Offset - src_size, block_size)) {
   1484           return -1;
   1485         }
   1486         if (m_File.AppendBlock(buffer, block_size) < 0) {
   1487           return -1;
   1488         }
   1489         src_size -= block_size;
   1490         if (pPause && pPause->NeedToPauseNow()) {
   1491           m_Pos = (void*)(uintptr_t)src_size;
   1492           return 1;
   1493         }
   1494       }
   1495     }
   1496     if ((m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0 &&
   1497         m_pParser->GetLastXRefOffset() == 0) {
   1498       InitOldObjNumOffsets();
   1499       uint32_t dwEnd = m_pParser->GetLastObjNum();
   1500       bool bObjStm = (m_dwFlags & FPDFCREATE_OBJECTSTREAM) != 0;
   1501       for (uint32_t objnum = 0; objnum <= dwEnd; objnum++) {
   1502         if (m_pParser->IsObjectFreeOrNull(objnum))
   1503           continue;
   1504 
   1505         m_ObjectOffset[objnum] = m_pParser->GetObjectPositionOrZero(objnum);
   1506         if (bObjStm) {
   1507           m_pXRefStream->AddObjectNumberToIndexArray(objnum);
   1508         }
   1509       }
   1510       if (bObjStm) {
   1511         m_pXRefStream->EndXRefStream(this);
   1512         m_pXRefStream->Start();
   1513       }
   1514     }
   1515     m_iStage = 20;
   1516   }
   1517   InitNewObjNumOffsets();
   1518   return m_iStage;
   1519 }
   1520 int32_t CPDF_Creator::WriteDoc_Stage2(IFX_Pause* pPause) {
   1521   ASSERT(m_iStage >= 20 || m_iStage < 30);
   1522   if (m_iStage == 20) {
   1523     if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 && m_pParser) {
   1524       m_Pos = (void*)(uintptr_t)0;
   1525       m_iStage = 21;
   1526     } else {
   1527       m_iStage = 25;
   1528     }
   1529   }
   1530   if (m_iStage == 21) {
   1531     int32_t iRet = WriteOldObjs(pPause);
   1532     if (iRet) {
   1533       return iRet;
   1534     }
   1535     m_iStage = 25;
   1536   }
   1537   if (m_iStage == 25) {
   1538     m_Pos = (void*)(uintptr_t)0;
   1539     m_iStage = 26;
   1540   }
   1541   if (m_iStage == 26) {
   1542     int32_t iRet =
   1543         WriteNewObjs((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0, pPause);
   1544     if (iRet) {
   1545       return iRet;
   1546     }
   1547     m_iStage = 27;
   1548   }
   1549   if (m_iStage == 27) {
   1550     if (m_pEncryptDict && m_pEncryptDict->IsInline()) {
   1551       m_dwLastObjNum += 1;
   1552       FX_FILESIZE saveOffset = m_Offset;
   1553       if (WriteIndirectObj(m_dwLastObjNum, m_pEncryptDict) < 0)
   1554         return -1;
   1555 
   1556       m_ObjectOffset.Add(m_dwLastObjNum, 1);
   1557       m_ObjectOffset[m_dwLastObjNum] = saveOffset;
   1558       m_dwEncryptObjNum = m_dwLastObjNum;
   1559       if (m_dwFlags & FPDFCREATE_INCREMENTAL)
   1560         m_NewObjNumArray.push_back(m_dwLastObjNum);
   1561     }
   1562     m_iStage = 80;
   1563   }
   1564   return m_iStage;
   1565 }
   1566 int32_t CPDF_Creator::WriteDoc_Stage3(IFX_Pause* pPause) {
   1567   ASSERT(m_iStage >= 80 || m_iStage < 90);
   1568   uint32_t dwLastObjNum = m_dwLastObjNum;
   1569   if (m_iStage == 80) {
   1570     m_XrefStart = m_Offset;
   1571     if (m_dwFlags & FPDFCREATE_OBJECTSTREAM) {
   1572       m_pXRefStream->End(this, true);
   1573       m_XrefStart = m_pXRefStream->m_PrevOffset;
   1574       m_iStage = 90;
   1575     } else if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 ||
   1576                !m_pParser->IsXRefStream()) {
   1577       if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 ||
   1578           m_pParser->GetLastXRefOffset() == 0) {
   1579         CFX_ByteString str;
   1580         str = m_ObjectOffset.GetPtrAt(1)
   1581                   ? "xref\r\n"
   1582                   : "xref\r\n0 1\r\n0000000000 65535 f\r\n";
   1583         if (m_File.AppendString(str.AsStringC()) < 0) {
   1584           return -1;
   1585         }
   1586         m_Pos = (void*)(uintptr_t)1;
   1587         m_iStage = 81;
   1588       } else {
   1589         if (m_File.AppendString("xref\r\n") < 0) {
   1590           return -1;
   1591         }
   1592         m_Pos = (void*)(uintptr_t)0;
   1593         m_iStage = 82;
   1594       }
   1595     } else {
   1596       m_iStage = 90;
   1597     }
   1598   }
   1599   if (m_iStage == 81) {
   1600     CFX_ByteString str;
   1601     uint32_t i = (uint32_t)(uintptr_t)m_Pos, j;
   1602     while (i <= dwLastObjNum) {
   1603       while (i <= dwLastObjNum && !m_ObjectOffset.GetPtrAt(i)) {
   1604         i++;
   1605       }
   1606       if (i > dwLastObjNum) {
   1607         break;
   1608       }
   1609       j = i;
   1610       while (j <= dwLastObjNum && m_ObjectOffset.GetPtrAt(j)) {
   1611         j++;
   1612       }
   1613       if (i == 1) {
   1614         str.Format("0 %d\r\n0000000000 65535 f\r\n", j);
   1615       } else {
   1616         str.Format("%d %d\r\n", i, j - i);
   1617       }
   1618       if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) {
   1619         return -1;
   1620       }
   1621       while (i < j) {
   1622         str.Format("%010d 00000 n\r\n", m_ObjectOffset[i++]);
   1623         if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) {
   1624           return -1;
   1625         }
   1626       }
   1627       if (i > dwLastObjNum) {
   1628         break;
   1629       }
   1630       if (pPause && pPause->NeedToPauseNow()) {
   1631         m_Pos = (void*)(uintptr_t)i;
   1632         return 1;
   1633       }
   1634     }
   1635     m_iStage = 90;
   1636   }
   1637   if (m_iStage == 82) {
   1638     CFX_ByteString str;
   1639     size_t iCount = m_NewObjNumArray.size();
   1640     size_t i = (size_t)(uintptr_t)m_Pos;
   1641     while (i < iCount) {
   1642       size_t j = i;
   1643       uint32_t objnum = m_NewObjNumArray[i];
   1644       while (j < iCount) {
   1645         if (++j == iCount)
   1646           break;
   1647         uint32_t dwCurrent = m_NewObjNumArray[j];
   1648         if (dwCurrent - objnum > 1)
   1649           break;
   1650         objnum = dwCurrent;
   1651       }
   1652       objnum = m_NewObjNumArray[i];
   1653       if (objnum == 1) {
   1654         str.Format("0 %d\r\n0000000000 65535 f\r\n", j - i + 1);
   1655       } else {
   1656         str.Format("%d %d\r\n", objnum, j - i);
   1657       }
   1658       if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0) {
   1659         return -1;
   1660       }
   1661       while (i < j) {
   1662         objnum = m_NewObjNumArray[i++];
   1663         str.Format("%010d 00000 n\r\n", m_ObjectOffset[objnum]);
   1664         if (m_File.AppendBlock(str.c_str(), str.GetLength()) < 0)
   1665           return -1;
   1666       }
   1667       if (pPause && (i % 100) == 0 && pPause->NeedToPauseNow()) {
   1668         m_Pos = (void*)(uintptr_t)i;
   1669         return 1;
   1670       }
   1671     }
   1672     m_iStage = 90;
   1673   }
   1674   return m_iStage;
   1675 }
   1676 
   1677 int32_t CPDF_Creator::WriteDoc_Stage4(IFX_Pause* pPause) {
   1678   ASSERT(m_iStage >= 90);
   1679   if ((m_dwFlags & FPDFCREATE_OBJECTSTREAM) == 0) {
   1680     bool bXRefStream =
   1681         (m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser->IsXRefStream();
   1682     if (!bXRefStream) {
   1683       if (m_File.AppendString("trailer\r\n<<") < 0) {
   1684         return -1;
   1685       }
   1686     } else {
   1687       if (m_File.AppendDWord(m_pDocument->GetLastObjNum() + 1) < 0) {
   1688         return -1;
   1689       }
   1690       if (m_File.AppendString(" 0 obj <<") < 0) {
   1691         return -1;
   1692       }
   1693     }
   1694     if (m_pParser) {
   1695       CPDF_Dictionary* p = m_pParser->GetTrailer();
   1696       for (const auto& it : *p) {
   1697         const CFX_ByteString& key = it.first;
   1698         CPDF_Object* pValue = it.second.get();
   1699         // TODO(ochang): Consolidate with similar check in
   1700         // PDF_CreatorWriteTrailer.
   1701         if (key == "Encrypt" || key == "Size" || key == "Filter" ||
   1702             key == "Index" || key == "Length" || key == "Prev" || key == "W" ||
   1703             key == "XRefStm" || key == "ID") {
   1704           continue;
   1705         }
   1706         if (m_File.AppendString(("/")) < 0) {
   1707           return -1;
   1708         }
   1709         if (m_File.AppendString(PDF_NameEncode(key).AsStringC()) < 0) {
   1710           return -1;
   1711         }
   1712         if (!pValue->IsInline()) {
   1713           if (m_File.AppendString(" ") < 0) {
   1714             return -1;
   1715           }
   1716           if (m_File.AppendDWord(pValue->GetObjNum()) < 0) {
   1717             return -1;
   1718           }
   1719           if (m_File.AppendString(" 0 R ") < 0) {
   1720             return -1;
   1721           }
   1722         } else {
   1723           FX_FILESIZE offset = 0;
   1724           if (PDF_CreatorAppendObject(pValue, &m_File, offset) < 0) {
   1725             return -1;
   1726           }
   1727         }
   1728       }
   1729     } else {
   1730       if (m_File.AppendString("\r\n/Root ") < 0) {
   1731         return -1;
   1732       }
   1733       if (m_File.AppendDWord(m_pDocument->GetRoot()->GetObjNum()) < 0) {
   1734         return -1;
   1735       }
   1736       if (m_File.AppendString(" 0 R\r\n") < 0) {
   1737         return -1;
   1738       }
   1739       if (m_pDocument->GetInfo()) {
   1740         if (m_File.AppendString("/Info ") < 0) {
   1741           return -1;
   1742         }
   1743         if (m_File.AppendDWord(m_pDocument->GetInfo()->GetObjNum()) < 0) {
   1744           return -1;
   1745         }
   1746         if (m_File.AppendString(" 0 R\r\n") < 0) {
   1747           return -1;
   1748         }
   1749       }
   1750     }
   1751     if (m_pEncryptDict) {
   1752       if (m_File.AppendString("/Encrypt") < 0) {
   1753         return -1;
   1754       }
   1755       uint32_t dwObjNum = m_pEncryptDict->GetObjNum();
   1756       if (dwObjNum == 0) {
   1757         dwObjNum = m_pDocument->GetLastObjNum() + 1;
   1758       }
   1759       if (m_File.AppendString(" ") < 0) {
   1760         return -1;
   1761       }
   1762       if (m_File.AppendDWord(dwObjNum) < 0) {
   1763         return -1;
   1764       }
   1765       if (m_File.AppendString(" 0 R ") < 0) {
   1766         return -1;
   1767       }
   1768     }
   1769     if (m_File.AppendString("/Size ") < 0) {
   1770       return -1;
   1771     }
   1772     if (m_File.AppendDWord(m_dwLastObjNum + (bXRefStream ? 2 : 1)) < 0) {
   1773       return -1;
   1774     }
   1775     if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0) {
   1776       FX_FILESIZE prev = m_pParser->GetLastXRefOffset();
   1777       if (prev) {
   1778         if (m_File.AppendString("/Prev ") < 0) {
   1779           return -1;
   1780         }
   1781         FX_CHAR offset_buf[20];
   1782         FXSYS_memset(offset_buf, 0, sizeof(offset_buf));
   1783         FXSYS_i64toa(prev, offset_buf, 10);
   1784         if (m_File.AppendBlock(offset_buf, FXSYS_strlen(offset_buf)) < 0) {
   1785           return -1;
   1786         }
   1787       }
   1788     }
   1789     if (m_pIDArray) {
   1790       if (m_File.AppendString(("/ID")) < 0) {
   1791         return -1;
   1792       }
   1793       FX_FILESIZE offset = 0;
   1794       if (PDF_CreatorAppendObject(m_pIDArray.get(), &m_File, offset) < 0) {
   1795         return -1;
   1796       }
   1797     }
   1798     if (!bXRefStream) {
   1799       if (m_File.AppendString(">>") < 0) {
   1800         return -1;
   1801       }
   1802     } else {
   1803       if (m_File.AppendString("/W[0 4 1]/Index[") < 0) {
   1804         return -1;
   1805       }
   1806       if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser &&
   1807           m_pParser->GetLastXRefOffset() == 0) {
   1808         uint32_t i = 0;
   1809         for (i = 0; i < m_dwLastObjNum; i++) {
   1810           if (!m_ObjectOffset.GetPtrAt(i)) {
   1811             continue;
   1812           }
   1813           if (m_File.AppendDWord(i) < 0) {
   1814             return -1;
   1815           }
   1816           if (m_File.AppendString(" 1 ") < 0) {
   1817             return -1;
   1818           }
   1819         }
   1820         if (m_File.AppendString("]/Length ") < 0) {
   1821           return -1;
   1822         }
   1823         if (m_File.AppendDWord(m_dwLastObjNum * 5) < 0) {
   1824           return -1;
   1825         }
   1826         if (m_File.AppendString(">>stream\r\n") < 0) {
   1827           return -1;
   1828         }
   1829         for (i = 0; i < m_dwLastObjNum; i++) {
   1830           FX_FILESIZE* offset = m_ObjectOffset.GetPtrAt(i);
   1831           if (!offset)
   1832             continue;
   1833           OutputIndex(&m_File, *offset);
   1834         }
   1835       } else {
   1836         size_t count = m_NewObjNumArray.size();
   1837         size_t i = 0;
   1838         for (i = 0; i < count; i++) {
   1839           if (m_File.AppendDWord(m_NewObjNumArray[i]) < 0)
   1840             return -1;
   1841           if (m_File.AppendString(" 1 ") < 0)
   1842             return -1;
   1843         }
   1844         if (m_File.AppendString("]/Length ") < 0)
   1845           return -1;
   1846         if (m_File.AppendDWord(count * 5) < 0)
   1847           return -1;
   1848         if (m_File.AppendString(">>stream\r\n") < 0)
   1849           return -1;
   1850         for (i = 0; i < count; i++) {
   1851           uint32_t objnum = m_NewObjNumArray[i];
   1852           FX_FILESIZE offset = m_ObjectOffset[objnum];
   1853           OutputIndex(&m_File, offset);
   1854         }
   1855       }
   1856       if (m_File.AppendString("\r\nendstream") < 0)
   1857         return -1;
   1858     }
   1859   }
   1860   if (m_File.AppendString("\r\nstartxref\r\n") < 0) {
   1861     return -1;
   1862   }
   1863   FX_CHAR offset_buf[20];
   1864   FXSYS_memset(offset_buf, 0, sizeof(offset_buf));
   1865   FXSYS_i64toa(m_XrefStart, offset_buf, 10);
   1866   if (m_File.AppendBlock(offset_buf, FXSYS_strlen(offset_buf)) < 0) {
   1867     return -1;
   1868   }
   1869   if (m_File.AppendString("\r\n%%EOF\r\n") < 0) {
   1870     return -1;
   1871   }
   1872   m_File.Flush();
   1873   return m_iStage = 100;
   1874 }
   1875 
   1876 void CPDF_Creator::Clear() {
   1877   m_pXRefStream.reset();
   1878   m_File.Clear();
   1879   m_NewObjNumArray.clear();
   1880   m_pIDArray.reset();
   1881 }
   1882 
   1883 bool CPDF_Creator::Create(const CFX_RetainPtr<IFX_WriteStream>& pFile,
   1884                           uint32_t flags) {
   1885   m_File.AttachFile(pFile);
   1886   return Create(flags);
   1887 }
   1888 
   1889 bool CPDF_Creator::Create(uint32_t flags) {
   1890   m_dwFlags = flags;
   1891   m_iStage = 0;
   1892   m_Offset = 0;
   1893   m_dwLastObjNum = m_pDocument->GetLastObjNum();
   1894   m_ObjectOffset.Clear();
   1895   m_NewObjNumArray.clear();
   1896   InitID();
   1897   if (flags & FPDFCREATE_PROGRESSIVE)
   1898     return true;
   1899   return Continue(nullptr) > -1;
   1900 }
   1901 
   1902 void CPDF_Creator::InitID(bool bDefault) {
   1903   CPDF_Array* pOldIDArray = m_pParser ? m_pParser->GetIDArray() : nullptr;
   1904   bool bNewId = !m_pIDArray;
   1905   if (bNewId) {
   1906     m_pIDArray = pdfium::MakeUnique<CPDF_Array>();
   1907     CPDF_Object* pID1 = pOldIDArray ? pOldIDArray->GetObjectAt(0) : nullptr;
   1908     if (pID1) {
   1909       m_pIDArray->Add(pID1->Clone());
   1910     } else {
   1911       std::vector<uint8_t> buffer =
   1912           PDF_GenerateFileID((uint32_t)(uintptr_t) this, m_dwLastObjNum);
   1913       CFX_ByteString bsBuffer(buffer.data(), buffer.size());
   1914       m_pIDArray->AddNew<CPDF_String>(bsBuffer, true);
   1915     }
   1916   }
   1917   if (!bDefault) {
   1918     return;
   1919   }
   1920   if (pOldIDArray) {
   1921     CPDF_Object* pID2 = pOldIDArray->GetObjectAt(1);
   1922     if ((m_dwFlags & FPDFCREATE_INCREMENTAL) && m_pEncryptDict && pID2) {
   1923       m_pIDArray->Add(pID2->Clone());
   1924       return;
   1925     }
   1926     std::vector<uint8_t> buffer =
   1927         PDF_GenerateFileID((uint32_t)(uintptr_t) this, m_dwLastObjNum);
   1928     CFX_ByteString bsBuffer(buffer.data(), buffer.size());
   1929     m_pIDArray->AddNew<CPDF_String>(bsBuffer, true);
   1930     return;
   1931   }
   1932   m_pIDArray->Add(m_pIDArray->GetObjectAt(0)->Clone());
   1933   if (m_pEncryptDict && !pOldIDArray && m_pParser && bNewId) {
   1934     if (m_pEncryptDict->GetStringFor("Filter") == "Standard") {
   1935       CFX_ByteString user_pass = m_pParser->GetPassword();
   1936       uint32_t flag = PDF_ENCRYPT_CONTENT;
   1937       CPDF_SecurityHandler handler;
   1938       handler.OnCreate(m_pEncryptDict, m_pIDArray.get(), user_pass.raw_str(),
   1939                        user_pass.GetLength(), flag);
   1940       if (m_bLocalCryptoHandler)
   1941         delete m_pCryptoHandler;
   1942       m_pCryptoHandler = new CPDF_CryptoHandler;
   1943       m_pCryptoHandler->Init(m_pEncryptDict, &handler);
   1944       m_bLocalCryptoHandler = true;
   1945       m_bSecurityChanged = true;
   1946     }
   1947   }
   1948 }
   1949 int32_t CPDF_Creator::Continue(IFX_Pause* pPause) {
   1950   if (m_iStage < 0) {
   1951     return m_iStage;
   1952   }
   1953   int32_t iRet = 0;
   1954   while (m_iStage < 100) {
   1955     if (m_iStage < 20) {
   1956       iRet = WriteDoc_Stage1(pPause);
   1957     } else if (m_iStage < 30) {
   1958       iRet = WriteDoc_Stage2(pPause);
   1959     } else if (m_iStage < 90) {
   1960       iRet = WriteDoc_Stage3(pPause);
   1961     } else {
   1962       iRet = WriteDoc_Stage4(pPause);
   1963     }
   1964     if (iRet < m_iStage) {
   1965       break;
   1966     }
   1967   }
   1968   if (iRet < 1 || m_iStage == 100) {
   1969     m_iStage = -1;
   1970     Clear();
   1971     return iRet > 99 ? 0 : (iRet < 1 ? -1 : iRet);
   1972   }
   1973   return m_iStage;
   1974 }
   1975 bool CPDF_Creator::SetFileVersion(int32_t fileVersion) {
   1976   if (fileVersion < 10 || fileVersion > 17) {
   1977     return false;
   1978   }
   1979   m_FileVersion = fileVersion;
   1980   return true;
   1981 }
   1982 void CPDF_Creator::RemoveSecurity() {
   1983   ResetStandardSecurity();
   1984   m_bSecurityChanged = true;
   1985   m_pEncryptDict = nullptr;
   1986   m_pCryptoHandler = nullptr;
   1987 }
   1988 void CPDF_Creator::ResetStandardSecurity() {
   1989   if (!m_bLocalCryptoHandler)
   1990     return;
   1991 
   1992   delete m_pCryptoHandler;
   1993   m_pCryptoHandler = nullptr;
   1994   m_bLocalCryptoHandler = false;
   1995 }
   1996