• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PDF_CreatorAppendObject(const CPDF_Object * pObj,CFX_FileBufferArchive * pFile,FX_FILESIZE & offset)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 
PDF_CreatorWriteTrailer(CPDF_Document * pDocument,CFX_FileBufferArchive * pFile,CPDF_Array * pIDArray)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 
PDF_CreatorWriteEncrypt(const CPDF_Dictionary * pEncryptDict,uint32_t dwObjNum,CFX_FileBufferArchive * pFile)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 
PDF_GenerateFileID(uint32_t dwSeed1,uint32_t dwSeed2)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 
AppendIndex0(CFX_ByteTextBuf & buffer,bool bFirstObject)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 
AppendIndex1(CFX_ByteTextBuf & buffer,FX_FILESIZE offset)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 
AppendIndex2(CFX_ByteTextBuf & buffer,uint32_t objnum,int32_t index)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 
IsXRefNeedEnd(CPDF_XRefStream * pXRef,uint32_t flag)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 
OutputIndex(CFX_FileBufferArchive * pFile,FX_FILESIZE offset)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 
CloneDict()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 
CPDF_FlateEncoder(CPDF_Stream * pStream,bool bFlateEncode)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 
CPDF_FlateEncoder(const uint8_t * pBuffer,uint32_t size,bool bFlateEncode,bool bXRefStream)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 
~CPDF_FlateEncoder()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 
CPDF_Encryptor(CPDF_CryptoHandler * pHandler,int objnum,uint8_t * src_data,uint32_t src_size)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 
~CPDF_Encryptor()506 CPDF_Encryptor::~CPDF_Encryptor() {
507   if (m_bNewBuf)
508     FX_Free(m_pData);
509 }
510 
511 }  // namespace
512 
CPDF_ObjectStream()513 CPDF_ObjectStream::CPDF_ObjectStream() : m_dwObjNum(0), m_index(0) {}
514 
~CPDF_ObjectStream()515 CPDF_ObjectStream::~CPDF_ObjectStream() {}
516 
Start()517 void CPDF_ObjectStream::Start() {
518   m_Items.clear();
519   m_Buffer.Clear();
520   m_dwObjNum = 0;
521   m_index = 0;
522 }
523 
CompressIndirectObject(uint32_t dwObjNum,const CPDF_Object * pObj)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 
CompressIndirectObject(uint32_t dwObjNum,const uint8_t * pBuffer,uint32_t dwSize)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 
End(CPDF_Creator * pCreator)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 
CPDF_XRefStream()604 CPDF_XRefStream::CPDF_XRefStream()
605     : m_PrevOffset(0), m_dwTempObjNum(0), m_iSeg(0) {}
606 
~CPDF_XRefStream()607 CPDF_XRefStream::~CPDF_XRefStream() {}
608 
Start()609 bool CPDF_XRefStream::Start() {
610   m_IndexArray.clear();
611   m_Buffer.Clear();
612   m_iSeg = 0;
613   return true;
614 }
CompressIndirectObject(uint32_t dwObjNum,const CPDF_Object * pObj,CPDF_Creator * pCreator)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 }
CompressIndirectObject(uint32_t dwObjNum,const uint8_t * pBuffer,uint32_t dwSize,CPDF_Creator * pCreator)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 
EndObjectStream(CPDF_Creator * pCreator,bool bEOF)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 }
GenerateXRefStream(CPDF_Creator * pCreator,bool bEOF)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 
End(CPDF_Creator * pCreator,bool bEOF)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 }
EndXRefStream(CPDF_Creator * pCreator)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 }
AddObjectNumberToIndexArray(uint32_t objnum)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 
CPDF_Creator(CPDF_Document * pDoc)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 
~CPDF_Creator()899 CPDF_Creator::~CPDF_Creator() {
900   ResetStandardSecurity();
901   if (m_bEncryptCloned) {
902     delete m_pEncryptDict;
903     m_pEncryptDict = nullptr;
904   }
905   Clear();
906 }
907 
WriteIndirectObjectToStream(const CPDF_Object * pObj)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 }
WriteIndirectObjectToStream(uint32_t objnum,const uint8_t * pBuffer,uint32_t dwSize)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 }
AppendObjectNumberToXRef(uint32_t objnum)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 }
WriteStream(const CPDF_Object * pStream,uint32_t objnum,CPDF_CryptoHandler * pCrypto)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 }
WriteIndirectObj(uint32_t objnum,const CPDF_Object * pObj)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 }
WriteIndirectObj(const CPDF_Object * pObj)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 }
WriteDirectObj(uint32_t objnum,const CPDF_Object * pObj,bool bEncrypt)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 }
WriteOldIndirectObject(uint32_t objnum)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 }
WriteOldObjs(IFX_Pause * pPause)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 
WriteNewObjs(bool bIncremental,IFX_Pause * pPause)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 
InitOldObjNumOffsets()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 
InitNewObjNumOffsets()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 
AppendNewObjNum(uint32_t objnum)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 
WriteDoc_Stage1(IFX_Pause * pPause)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 }
WriteDoc_Stage2(IFX_Pause * pPause)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 }
WriteDoc_Stage3(IFX_Pause * pPause)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 
WriteDoc_Stage4(IFX_Pause * pPause)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 
Clear()1876 void CPDF_Creator::Clear() {
1877   m_pXRefStream.reset();
1878   m_File.Clear();
1879   m_NewObjNumArray.clear();
1880   m_pIDArray.reset();
1881 }
1882 
Create(const CFX_RetainPtr<IFX_WriteStream> & pFile,uint32_t flags)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 
Create(uint32_t flags)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 
InitID(bool bDefault)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 }
Continue(IFX_Pause * pPause)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 }
SetFileVersion(int32_t fileVersion)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 }
RemoveSecurity()1982 void CPDF_Creator::RemoveSecurity() {
1983   ResetStandardSecurity();
1984   m_bSecurityChanged = true;
1985   m_pEncryptDict = nullptr;
1986   m_pCryptoHandler = nullptr;
1987 }
ResetStandardSecurity()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