blob: b6658ee5fb44353e7f5c4f5903b6357792455128 [file] [log] [blame]
npm014b0122016-11-07 08:42:11 -08001// Copyright 2016 PDFium Authors. All rights reserved.
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhang95e854f2015-06-13 00:58:06 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
tsepez1aff2652016-11-22 10:45:59 -08007#include "core/fpdfapi/page/cpdf_streamparser.h"
Lei Zhanga9fa50f2015-11-10 09:45:32 -08008
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07009#include <limits.h>
Lei Zhang37890562015-09-25 22:51:39 -070010
Henrique Nakashima09150872017-06-08 10:08:08 -040011#include <algorithm>
tsepez06104a82016-11-21 16:22:10 -080012#include <memory>
Henrique Nakashima09150872017-06-08 10:08:08 -040013#include <sstream>
tsepez0e606b52016-11-18 16:22:41 -080014#include <utility>
15
Lei Zhang26170562018-04-17 17:01:52 +000016#include "constants/stream_dict_common.h"
dsinclair39c62fd2016-09-29 12:49:17 -070017#include "core/fpdfapi/cpdf_modulemgr.h"
tsepez9fa95ef2016-10-11 12:29:38 -070018#include "core/fpdfapi/page/cpdf_docpagedata.h"
dsinclair488b7ad2016-10-04 11:55:50 -070019#include "core/fpdfapi/parser/cpdf_array.h"
20#include "core/fpdfapi/parser/cpdf_boolean.h"
21#include "core/fpdfapi/parser/cpdf_dictionary.h"
22#include "core/fpdfapi/parser/cpdf_document.h"
23#include "core/fpdfapi/parser/cpdf_name.h"
24#include "core/fpdfapi/parser/cpdf_null.h"
25#include "core/fpdfapi/parser/cpdf_number.h"
26#include "core/fpdfapi/parser/cpdf_stream.h"
dsinclair488b7ad2016-10-04 11:55:50 -070027#include "core/fpdfapi/parser/cpdf_string.h"
28#include "core/fpdfapi/parser/fpdf_parser_decode.h"
29#include "core/fpdfapi/parser/fpdf_parser_utility.h"
Lei Zhang7acd8262017-09-19 14:34:37 -070030#include "core/fxcodec/codec/ccodec_jpegmodule.h"
Lei Zhang4b8d3632017-09-19 14:18:48 -070031#include "core/fxcodec/codec/ccodec_scanlinedecoder.h"
Dan Sinclaircfb19442017-04-20 13:13:04 -040032#include "core/fxcrt/fx_extension.h"
Lei Zhanga9fa50f2015-11-10 09:45:32 -080033
thestig8e957ba2016-04-28 14:45:28 -070034namespace {
35
Nicolas Pena6438c4f2017-01-27 10:05:36 -050036const uint32_t kMaxNestedParsingLevel = 512;
Ryan Harrison875e98c2017-09-27 10:53:11 -040037const size_t kMaxStringLength = 32767;
thestig8e957ba2016-04-28 14:45:28 -070038
tsepez974b4a62016-12-13 12:48:13 -080039uint32_t DecodeAllScanlines(std::unique_ptr<CCodec_ScanlineDecoder> pDecoder,
Nicolas Pena995a6012017-06-20 17:42:39 -040040 uint8_t** dest_buf,
41 uint32_t* dest_size) {
npm014b0122016-11-07 08:42:11 -080042 if (!pDecoder)
Wei Li89409932016-03-28 10:33:33 -070043 return FX_INVALID_OFFSET;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070044 int ncomps = pDecoder->CountComps();
45 int bpc = pDecoder->GetBPC();
46 int width = pDecoder->GetWidth();
47 int height = pDecoder->GetHeight();
48 int pitch = (width * ncomps * bpc + 7) / 8;
tsepez974b4a62016-12-13 12:48:13 -080049 if (height == 0 || pitch > (1 << 30) / height)
Wei Li89409932016-03-28 10:33:33 -070050 return FX_INVALID_OFFSET;
tsepez974b4a62016-12-13 12:48:13 -080051
Nicolas Pena995a6012017-06-20 17:42:39 -040052 *dest_buf = FX_Alloc2D(uint8_t, pitch, height);
53 *dest_size = pitch * height; // Safe since checked alloc returned.
54 for (int row = 0; row < height; ++row) {
Lei Zhange95f39f2015-10-01 14:08:32 -070055 const uint8_t* pLine = pDecoder->GetScanline(row);
56 if (!pLine)
Nico Weber9d8ec5a2015-08-04 13:00:21 -070057 break;
Lei Zhange95f39f2015-10-01 14:08:32 -070058
Nicolas Pena995a6012017-06-20 17:42:39 -040059 memcpy(*dest_buf + row * pitch, pLine, pitch);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070060 }
tsepez974b4a62016-12-13 12:48:13 -080061 return pDecoder->GetSrcOffset();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070062}
Wei Lidc4d5042016-01-19 13:19:44 -080063
Jane Liu548334e2017-08-03 16:33:40 -040064uint32_t DecodeInlineStream(const uint8_t* src_buf,
65 uint32_t limit,
66 int width,
67 int height,
Ryan Harrison275e2602017-09-18 14:23:18 -040068 const ByteString& decoder,
Jane Liu548334e2017-08-03 16:33:40 -040069 CPDF_Dictionary* pParam,
70 uint8_t** dest_buf,
71 uint32_t* dest_size) {
Lei Zhangd983b092015-12-14 16:58:33 -080072 if (decoder == "CCITTFaxDecode" || decoder == "CCF") {
tsepez974b4a62016-12-13 12:48:13 -080073 std::unique_ptr<CCodec_ScanlineDecoder> pDecoder =
Nico Weber9d8ec5a2015-08-04 13:00:21 -070074 FPDFAPI_CreateFaxDecoder(src_buf, limit, width, height, pParam);
tsepez974b4a62016-12-13 12:48:13 -080075 return DecodeAllScanlines(std::move(pDecoder), dest_buf, dest_size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070076 }
npm014b0122016-11-07 08:42:11 -080077 if (decoder == "ASCII85Decode" || decoder == "A85")
Dan Sinclair4d6f03a2015-11-02 16:12:41 -050078 return A85Decode(src_buf, limit, dest_buf, dest_size);
npm014b0122016-11-07 08:42:11 -080079 if (decoder == "ASCIIHexDecode" || decoder == "AHx")
Dan Sinclair4d6f03a2015-11-02 16:12:41 -050080 return HexDecode(src_buf, limit, dest_buf, dest_size);
Lei Zhangd983b092015-12-14 16:58:33 -080081 if (decoder == "FlateDecode" || decoder == "Fl") {
Nicolas Pena995a6012017-06-20 17:42:39 -040082 return FPDFAPI_FlateOrLZWDecode(false, src_buf, limit, pParam, *dest_size,
Nico Weber9d8ec5a2015-08-04 13:00:21 -070083 dest_buf, dest_size);
84 }
Lei Zhangd983b092015-12-14 16:58:33 -080085 if (decoder == "LZWDecode" || decoder == "LZW") {
tsepez12f3e4a2016-11-02 15:17:29 -070086 return FPDFAPI_FlateOrLZWDecode(true, src_buf, limit, pParam, 0, dest_buf,
Nico Weber9d8ec5a2015-08-04 13:00:21 -070087 dest_size);
88 }
Lei Zhangd983b092015-12-14 16:58:33 -080089 if (decoder == "DCTDecode" || decoder == "DCT") {
tsepez974b4a62016-12-13 12:48:13 -080090 std::unique_ptr<CCodec_ScanlineDecoder> pDecoder =
Nico Weber9d8ec5a2015-08-04 13:00:21 -070091 CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder(
92 src_buf, limit, width, height, 0,
tsepez16b703c2016-10-26 08:45:31 -070093 !pParam || pParam->GetIntegerFor("ColorTransform", 1));
tsepez974b4a62016-12-13 12:48:13 -080094 return DecodeAllScanlines(std::move(pDecoder), dest_buf, dest_size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070095 }
npm014b0122016-11-07 08:42:11 -080096 if (decoder == "RunLengthDecode" || decoder == "RL")
Nico Weber9d8ec5a2015-08-04 13:00:21 -070097 return RunLengthDecode(src_buf, limit, dest_buf, dest_size);
Nicolas Pena995a6012017-06-20 17:42:39 -040098 *dest_size = 0;
99 *dest_buf = 0;
Lei Zhanga12159b2017-03-15 13:26:37 -0700100 return 0xFFFFFFFF;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700101}
Wei Lidc4d5042016-01-19 13:19:44 -0800102
Jane Liu548334e2017-08-03 16:33:40 -0400103} // namespace
104
Tom Sepez6058efd2018-04-06 23:48:24 +0000105CPDF_StreamParser::CPDF_StreamParser(pdfium::span<const uint8_t> span)
106 : m_pBuf(span) {}
npme883afc2016-10-05 13:43:25 -0700107
Tom Sepez6058efd2018-04-06 23:48:24 +0000108CPDF_StreamParser::CPDF_StreamParser(pdfium::span<const uint8_t> span,
Dan Sinclairb872a932017-09-21 17:05:15 -0400109 const WeakPtr<ByteStringPool>& pPool)
Tom Sepez6058efd2018-04-06 23:48:24 +0000110 : m_pPool(pPool), m_pBuf(span) {}
npme883afc2016-10-05 13:43:25 -0700111
tsepez06104a82016-11-21 16:22:10 -0800112CPDF_StreamParser::~CPDF_StreamParser() {}
npme883afc2016-10-05 13:43:25 -0700113
tsepez06104a82016-11-21 16:22:10 -0800114std::unique_ptr<CPDF_Stream> CPDF_StreamParser::ReadInlineStream(
115 CPDF_Document* pDoc,
tsepez12ff1eb2016-11-21 17:47:29 -0800116 std::unique_ptr<CPDF_Dictionary> pDict,
tsepez06104a82016-11-21 16:22:10 -0800117 CPDF_Object* pCSObj) {
Tom Sepez5b1fd5c2018-04-11 18:09:30 +0000118 if (m_Pos < m_pBuf.size() && PDFCharIsWhitespace(m_pBuf[m_Pos]))
119 m_Pos++;
120
Tom Sepez6058efd2018-04-06 23:48:24 +0000121 if (m_Pos == m_pBuf.size())
Dan Sinclair69472872015-10-28 10:20:35 -0400122 return nullptr;
123
Ryan Harrison275e2602017-09-18 14:23:18 -0400124 ByteString Decoder;
Dan Sinclair69472872015-10-28 10:20:35 -0400125 CPDF_Dictionary* pParam = nullptr;
dsinclair38fd8442016-09-15 10:15:32 -0700126 CPDF_Object* pFilter = pDict->GetDirectObjectFor("Filter");
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400127 if (pFilter) {
128 if (CPDF_Array* pArray = pFilter->AsArray()) {
Wei Li9b761132016-01-29 15:44:20 -0800129 Decoder = pArray->GetStringAt(0);
Lei Zhang26170562018-04-17 17:01:52 +0000130 CPDF_Array* pParams = pDict->GetArrayFor(pdfium::stream::kDecodeParms);
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400131 if (pParams)
Wei Li9b761132016-01-29 15:44:20 -0800132 pParam = pParams->GetDictAt(0);
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400133 } else {
134 Decoder = pFilter->GetString();
Lei Zhang26170562018-04-17 17:01:52 +0000135 pParam = pDict->GetDictFor(pdfium::stream::kDecodeParms);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700136 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700137 }
dsinclair38fd8442016-09-15 10:15:32 -0700138 uint32_t width = pDict->GetIntegerFor("Width");
139 uint32_t height = pDict->GetIntegerFor("Height");
tsepezb5e8f142016-03-25 15:18:35 -0700140 uint32_t OrigSize = 0;
Lei Zhang96660d62015-12-14 18:27:25 -0800141 if (pCSObj) {
dsinclair38fd8442016-09-15 10:15:32 -0700142 uint32_t bpc = pDict->GetIntegerFor("BitsPerComponent");
tsepezb5e8f142016-03-25 15:18:35 -0700143 uint32_t nComponents = 1;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700144 CPDF_ColorSpace* pCS = pDoc->LoadColorSpace(pCSObj);
thestig823df2a2016-07-29 06:15:39 -0700145 if (pCS) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700146 nComponents = pCS->CountComponents();
147 pDoc->GetPageData()->ReleaseColorSpace(pCSObj);
thestig823df2a2016-07-29 06:15:39 -0700148 } else {
149 nComponents = 3;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700150 }
tsepezb5e8f142016-03-25 15:18:35 -0700151 uint32_t pitch = width;
thestig823df2a2016-07-29 06:15:39 -0700152 if (bpc && pitch > INT_MAX / bpc)
thestig4997b222016-06-07 10:46:22 -0700153 return nullptr;
thestig823df2a2016-07-29 06:15:39 -0700154
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700155 pitch *= bpc;
thestig823df2a2016-07-29 06:15:39 -0700156 if (nComponents && pitch > INT_MAX / nComponents)
thestig4997b222016-06-07 10:46:22 -0700157 return nullptr;
thestig823df2a2016-07-29 06:15:39 -0700158
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700159 pitch *= nComponents;
thestig823df2a2016-07-29 06:15:39 -0700160 if (pitch > INT_MAX - 7)
thestig4997b222016-06-07 10:46:22 -0700161 return nullptr;
thestig823df2a2016-07-29 06:15:39 -0700162
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700163 pitch += 7;
164 pitch /= 8;
165 OrigSize = pitch;
166 } else {
thestig823df2a2016-07-29 06:15:39 -0700167 if (width > INT_MAX - 7)
thestig4997b222016-06-07 10:46:22 -0700168 return nullptr;
thestig823df2a2016-07-29 06:15:39 -0700169
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700170 OrigSize = ((width + 7) / 8);
171 }
thestig823df2a2016-07-29 06:15:39 -0700172 if (height && OrigSize > INT_MAX / height)
thestig4997b222016-06-07 10:46:22 -0700173 return nullptr;
thestig823df2a2016-07-29 06:15:39 -0700174
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700175 OrigSize *= height;
tsepez47fb8c02016-12-15 13:51:34 -0800176 std::unique_ptr<uint8_t, FxFreeDeleter> pData;
tsepezb5e8f142016-03-25 15:18:35 -0700177 uint32_t dwStreamSize;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700178 if (Decoder.IsEmpty()) {
Tom Sepez6058efd2018-04-06 23:48:24 +0000179 if (OrigSize > m_pBuf.size() - m_Pos)
180 OrigSize = m_pBuf.size() - m_Pos;
tsepez47fb8c02016-12-15 13:51:34 -0800181 pData.reset(FX_Alloc(uint8_t, OrigSize));
Tom Sepez6058efd2018-04-06 23:48:24 +0000182 memcpy(pData.get(), &m_pBuf[m_Pos], OrigSize);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700183 dwStreamSize = OrigSize;
184 m_Pos += OrigSize;
185 } else {
tsepez04a40702016-12-19 16:09:57 -0800186 uint8_t* pIgnore = nullptr;
tsepezb5e8f142016-03-25 15:18:35 -0700187 uint32_t dwDestSize = OrigSize;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700188 dwStreamSize =
Tom Sepez6058efd2018-04-06 23:48:24 +0000189 DecodeInlineStream(&m_pBuf[m_Pos], m_pBuf.size() - m_Pos, width, height,
Jane Liu18ae06d2017-07-18 10:15:16 -0400190 Decoder, pParam, &pIgnore, &dwDestSize);
tsepez47fb8c02016-12-15 13:51:34 -0800191 FX_Free(pIgnore);
npm014b0122016-11-07 08:42:11 -0800192 if (static_cast<int>(dwStreamSize) < 0)
thestig4997b222016-06-07 10:46:22 -0700193 return nullptr;
thestig5cc24652016-04-26 11:46:02 -0700194
195 uint32_t dwSavePos = m_Pos;
196 m_Pos += dwStreamSize;
197 while (1) {
198 uint32_t dwPrevPos = m_Pos;
199 CPDF_StreamParser::SyntaxType type = ParseNextElement();
200 if (type == CPDF_StreamParser::EndOfData)
201 break;
202
203 if (type != CPDF_StreamParser::Keyword) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700204 dwStreamSize += m_Pos - dwPrevPos;
thestig5cc24652016-04-26 11:46:02 -0700205 continue;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700206 }
tsepez2763fba2017-01-24 10:50:20 -0800207 if (GetWord() == "EI") {
thestig5cc24652016-04-26 11:46:02 -0700208 m_Pos = dwPrevPos;
209 break;
210 }
211 dwStreamSize += m_Pos - dwPrevPos;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700212 }
thestig5cc24652016-04-26 11:46:02 -0700213 m_Pos = dwSavePos;
tsepez47fb8c02016-12-15 13:51:34 -0800214 pData.reset(FX_Alloc(uint8_t, dwStreamSize));
Tom Sepez6058efd2018-04-06 23:48:24 +0000215 memcpy(pData.get(), &m_pBuf[m_Pos], dwStreamSize);
thestig5cc24652016-04-26 11:46:02 -0700216 m_Pos += dwStreamSize;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700217 }
Henrique Nakashima09150872017-06-08 10:08:08 -0400218 pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(dwStreamSize));
tsepez47fb8c02016-12-15 13:51:34 -0800219 return pdfium::MakeUnique<CPDF_Stream>(std::move(pData), dwStreamSize,
220 std::move(pDict));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700221}
Lei Zhang61aad4f2015-11-10 10:28:56 -0800222
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700223CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement() {
tsepez06104a82016-11-21 16:22:10 -0800224 m_pLastObj.reset();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700225 m_WordSize = 0;
Dan Sinclair90c90052015-10-28 13:05:52 -0400226 if (!PositionIsInBounds())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700227 return EndOfData;
Dan Sinclair69472872015-10-28 10:20:35 -0400228
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700229 int ch = m_pBuf[m_Pos++];
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700230 while (1) {
Dan Sinclair69472872015-10-28 10:20:35 -0400231 while (PDFCharIsWhitespace(ch)) {
Dan Sinclair90c90052015-10-28 13:05:52 -0400232 if (!PositionIsInBounds())
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700233 return EndOfData;
Dan Sinclair69472872015-10-28 10:20:35 -0400234
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700235 ch = m_pBuf[m_Pos++];
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700236 }
Dan Sinclair69472872015-10-28 10:20:35 -0400237
238 if (ch != '%')
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700239 break;
Dan Sinclair69472872015-10-28 10:20:35 -0400240
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700241 while (1) {
Dan Sinclair90c90052015-10-28 13:05:52 -0400242 if (!PositionIsInBounds())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700243 return EndOfData;
Dan Sinclair69472872015-10-28 10:20:35 -0400244
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245 ch = m_pBuf[m_Pos++];
Dan Sinclair806af3a2015-10-28 17:24:07 -0400246 if (PDFCharIsLineEnding(ch))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700247 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700248 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700249 }
Dan Sinclair69472872015-10-28 10:20:35 -0400250
251 if (PDFCharIsDelimiter(ch) && ch != '/') {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700252 m_Pos--;
Nicolas Pena6438c4f2017-01-27 10:05:36 -0500253 m_pLastObj = ReadNextObject(false, false, 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700254 return Others;
255 }
Dan Sinclair69472872015-10-28 10:20:35 -0400256
tsepez06104a82016-11-21 16:22:10 -0800257 bool bIsNumber = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700258 while (1) {
Tom Sepeze96e6fd2018-04-03 15:02:37 +0000259 if (m_WordSize < kMaxWordLength)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700260 m_WordBuffer[m_WordSize++] = ch;
Dan Sinclair69472872015-10-28 10:20:35 -0400261
262 if (!PDFCharIsNumeric(ch))
npme883afc2016-10-05 13:43:25 -0700263 bIsNumber = false;
Dan Sinclair69472872015-10-28 10:20:35 -0400264
Dan Sinclair90c90052015-10-28 13:05:52 -0400265 if (!PositionIsInBounds())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700266 break;
Dan Sinclair69472872015-10-28 10:20:35 -0400267
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700268 ch = m_pBuf[m_Pos++];
Dan Sinclair69472872015-10-28 10:20:35 -0400269
270 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700271 m_Pos--;
272 break;
273 }
274 }
Dan Sinclair69472872015-10-28 10:20:35 -0400275
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700276 m_WordBuffer[m_WordSize] = 0;
Dan Sinclair69472872015-10-28 10:20:35 -0400277 if (bIsNumber)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700278 return Number;
Tom Sepez282cee12016-03-24 10:43:11 -0700279
Dan Sinclair69472872015-10-28 10:20:35 -0400280 if (m_WordBuffer[0] == '/')
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700281 return Name;
Dan Sinclair69472872015-10-28 10:20:35 -0400282
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700283 if (m_WordSize == 4) {
Tom Sepez282cee12016-03-24 10:43:11 -0700284 if (memcmp(m_WordBuffer, "true", 4) == 0) {
tsepez06104a82016-11-21 16:22:10 -0800285 m_pLastObj = pdfium::MakeUnique<CPDF_Boolean>(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700286 return Others;
287 }
Tom Sepez282cee12016-03-24 10:43:11 -0700288 if (memcmp(m_WordBuffer, "null", 4) == 0) {
tsepez06104a82016-11-21 16:22:10 -0800289 m_pLastObj = pdfium::MakeUnique<CPDF_Null>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700290 return Others;
291 }
292 } else if (m_WordSize == 5) {
Tom Sepez282cee12016-03-24 10:43:11 -0700293 if (memcmp(m_WordBuffer, "false", 5) == 0) {
tsepez06104a82016-11-21 16:22:10 -0800294 m_pLastObj = pdfium::MakeUnique<CPDF_Boolean>(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700295 return Others;
296 }
297 }
298 return Keyword;
299}
Dan Sinclair80189602015-10-28 14:24:14 -0400300
tsepez06104a82016-11-21 16:22:10 -0800301std::unique_ptr<CPDF_Object> CPDF_StreamParser::ReadNextObject(
302 bool bAllowNestedArray,
Nicolas Pena6438c4f2017-01-27 10:05:36 -0500303 bool bInArray,
304 uint32_t dwRecursionLevel) {
npme883afc2016-10-05 13:43:25 -0700305 bool bIsNumber;
Nicolas Pena6438c4f2017-01-27 10:05:36 -0500306 // Must get the next word before returning to avoid infinite loops.
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700307 GetNextWord(bIsNumber);
Nicolas Pena6438c4f2017-01-27 10:05:36 -0500308 if (!m_WordSize || dwRecursionLevel > kMaxNestedParsingLevel)
thestig8e957ba2016-04-28 14:45:28 -0700309 return nullptr;
310
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700311 if (bIsNumber) {
312 m_WordBuffer[m_WordSize] = 0;
tsepez06104a82016-11-21 16:22:10 -0800313 return pdfium::MakeUnique<CPDF_Number>(
Ryan Harrison275e2602017-09-18 14:23:18 -0400314 ByteStringView(m_WordBuffer, m_WordSize));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700315 }
thestig8e957ba2016-04-28 14:45:28 -0700316
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700317 int first_char = m_WordBuffer[0];
318 if (first_char == '/') {
Ryan Harrison275e2602017-09-18 14:23:18 -0400319 ByteString name =
320 PDF_NameDecode(ByteStringView(m_WordBuffer + 1, m_WordSize - 1));
tsepez06104a82016-11-21 16:22:10 -0800321 return pdfium::MakeUnique<CPDF_Name>(m_pPool, name);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700322 }
thestig8e957ba2016-04-28 14:45:28 -0700323
tsepez698c5712016-09-28 16:47:07 -0700324 if (first_char == '(') {
Ryan Harrison275e2602017-09-18 14:23:18 -0400325 ByteString str = ReadString();
tsepez06104a82016-11-21 16:22:10 -0800326 return pdfium::MakeUnique<CPDF_String>(m_pPool, str, false);
tsepez698c5712016-09-28 16:47:07 -0700327 }
thestig8e957ba2016-04-28 14:45:28 -0700328
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700329 if (first_char == '<') {
thestig8e957ba2016-04-28 14:45:28 -0700330 if (m_WordSize == 1)
tsepez06104a82016-11-21 16:22:10 -0800331 return pdfium::MakeUnique<CPDF_String>(m_pPool, ReadHexString(), true);
thestig8e957ba2016-04-28 14:45:28 -0700332
tsepez06104a82016-11-21 16:22:10 -0800333 auto pDict = pdfium::MakeUnique<CPDF_Dictionary>(m_pPool);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700334 while (1) {
335 GetNextWord(bIsNumber);
thestig8e957ba2016-04-28 14:45:28 -0700336 if (m_WordSize == 2 && m_WordBuffer[0] == '>')
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700337 break;
thestig8e957ba2016-04-28 14:45:28 -0700338
tsepez06104a82016-11-21 16:22:10 -0800339 if (!m_WordSize || m_WordBuffer[0] != '/')
Lei Zhang4880d1a2015-12-18 17:05:11 -0800340 return nullptr;
thestig8e957ba2016-04-28 14:45:28 -0700341
Ryan Harrison275e2602017-09-18 14:23:18 -0400342 ByteString key =
343 PDF_NameDecode(ByteStringView(m_WordBuffer + 1, m_WordSize - 1));
Nicolas Pena6438c4f2017-01-27 10:05:36 -0500344 std::unique_ptr<CPDF_Object> pObj =
345 ReadNextObject(true, bInArray, dwRecursionLevel + 1);
tsepez06104a82016-11-21 16:22:10 -0800346 if (!pObj)
Lei Zhang4880d1a2015-12-18 17:05:11 -0800347 return nullptr;
tsepez06104a82016-11-21 16:22:10 -0800348
tsepez0e606b52016-11-18 16:22:41 -0800349 if (!key.IsEmpty())
350 pDict->SetFor(key, std::move(pObj));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700351 }
tsepez06104a82016-11-21 16:22:10 -0800352 return std::move(pDict);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700353 }
thestig8e957ba2016-04-28 14:45:28 -0700354
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700355 if (first_char == '[') {
Nicolas Pena6438c4f2017-01-27 10:05:36 -0500356 if ((!bAllowNestedArray && bInArray))
thestig8e957ba2016-04-28 14:45:28 -0700357 return nullptr;
thestig8e957ba2016-04-28 14:45:28 -0700358
tsepez06104a82016-11-21 16:22:10 -0800359 auto pArray = pdfium::MakeUnique<CPDF_Array>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700360 while (1) {
tsepez06104a82016-11-21 16:22:10 -0800361 std::unique_ptr<CPDF_Object> pObj =
Nicolas Pena6438c4f2017-01-27 10:05:36 -0500362 ReadNextObject(bAllowNestedArray, true, dwRecursionLevel + 1);
Lei Zhang4880d1a2015-12-18 17:05:11 -0800363 if (pObj) {
tsepez06104a82016-11-21 16:22:10 -0800364 pArray->Add(std::move(pObj));
Lei Zhang4880d1a2015-12-18 17:05:11 -0800365 continue;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700366 }
thestig8e957ba2016-04-28 14:45:28 -0700367 if (!m_WordSize || m_WordBuffer[0] == ']')
Lei Zhang4880d1a2015-12-18 17:05:11 -0800368 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700369 }
tsepez06104a82016-11-21 16:22:10 -0800370 return std::move(pArray);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700371 }
thestig8e957ba2016-04-28 14:45:28 -0700372
373 if (m_WordSize == 5 && !memcmp(m_WordBuffer, "false", 5))
tsepez06104a82016-11-21 16:22:10 -0800374 return pdfium::MakeUnique<CPDF_Boolean>(false);
thestig8e957ba2016-04-28 14:45:28 -0700375
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700376 if (m_WordSize == 4) {
thestig8e957ba2016-04-28 14:45:28 -0700377 if (memcmp(m_WordBuffer, "true", 4) == 0)
tsepez06104a82016-11-21 16:22:10 -0800378 return pdfium::MakeUnique<CPDF_Boolean>(true);
thestig8e957ba2016-04-28 14:45:28 -0700379 if (memcmp(m_WordBuffer, "null", 4) == 0)
tsepez06104a82016-11-21 16:22:10 -0800380 return pdfium::MakeUnique<CPDF_Null>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700381 }
thestig8e957ba2016-04-28 14:45:28 -0700382
383 return nullptr;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700384}
Wei Lidc4d5042016-01-19 13:19:44 -0800385
npm014b0122016-11-07 08:42:11 -0800386// TODO(npm): the following methods are almost identical in cpdf_syntaxparser
npme883afc2016-10-05 13:43:25 -0700387void CPDF_StreamParser::GetNextWord(bool& bIsNumber) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700388 m_WordSize = 0;
npme883afc2016-10-05 13:43:25 -0700389 bIsNumber = true;
Dan Sinclair90c90052015-10-28 13:05:52 -0400390 if (!PositionIsInBounds())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700391 return;
Dan Sinclair69472872015-10-28 10:20:35 -0400392
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700393 int ch = m_pBuf[m_Pos++];
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700394 while (1) {
Dan Sinclair69472872015-10-28 10:20:35 -0400395 while (PDFCharIsWhitespace(ch)) {
Dan Sinclair90c90052015-10-28 13:05:52 -0400396 if (!PositionIsInBounds()) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700397 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700398 }
399 ch = m_pBuf[m_Pos++];
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700400 }
Dan Sinclair69472872015-10-28 10:20:35 -0400401
402 if (ch != '%')
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700403 break;
Dan Sinclair69472872015-10-28 10:20:35 -0400404
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700405 while (1) {
Dan Sinclair90c90052015-10-28 13:05:52 -0400406 if (!PositionIsInBounds())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700407 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700408 ch = m_pBuf[m_Pos++];
Dan Sinclair806af3a2015-10-28 17:24:07 -0400409 if (PDFCharIsLineEnding(ch))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700410 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700411 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700412 }
Dan Sinclair69472872015-10-28 10:20:35 -0400413
414 if (PDFCharIsDelimiter(ch)) {
npme883afc2016-10-05 13:43:25 -0700415 bIsNumber = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700416 m_WordBuffer[m_WordSize++] = ch;
417 if (ch == '/') {
418 while (1) {
Dan Sinclair90c90052015-10-28 13:05:52 -0400419 if (!PositionIsInBounds())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700420 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700421 ch = m_pBuf[m_Pos++];
Dan Sinclair69472872015-10-28 10:20:35 -0400422 if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700423 m_Pos--;
424 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700425 }
Tom Sepeze96e6fd2018-04-03 15:02:37 +0000426 if (m_WordSize < kMaxWordLength)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700427 m_WordBuffer[m_WordSize++] = ch;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700428 }
429 } else if (ch == '<') {
Dan Sinclair90c90052015-10-28 13:05:52 -0400430 if (!PositionIsInBounds())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700431 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700432 ch = m_pBuf[m_Pos++];
Dan Sinclair69472872015-10-28 10:20:35 -0400433 if (ch == '<')
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700434 m_WordBuffer[m_WordSize++] = ch;
Dan Sinclair69472872015-10-28 10:20:35 -0400435 else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700436 m_Pos--;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700437 } else if (ch == '>') {
Dan Sinclair90c90052015-10-28 13:05:52 -0400438 if (!PositionIsInBounds())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700439 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700440 ch = m_pBuf[m_Pos++];
Dan Sinclair69472872015-10-28 10:20:35 -0400441 if (ch == '>')
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700442 m_WordBuffer[m_WordSize++] = ch;
Dan Sinclair69472872015-10-28 10:20:35 -0400443 else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700444 m_Pos--;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700445 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700446 return;
447 }
Dan Sinclair69472872015-10-28 10:20:35 -0400448
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700449 while (1) {
Tom Sepeze96e6fd2018-04-03 15:02:37 +0000450 if (m_WordSize < kMaxWordLength)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700451 m_WordBuffer[m_WordSize++] = ch;
Dan Sinclair69472872015-10-28 10:20:35 -0400452 if (!PDFCharIsNumeric(ch))
npme883afc2016-10-05 13:43:25 -0700453 bIsNumber = false;
Dan Sinclair90c90052015-10-28 13:05:52 -0400454 if (!PositionIsInBounds())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700455 return;
Tom Sepeze96e6fd2018-04-03 15:02:37 +0000456
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700457 ch = m_pBuf[m_Pos++];
Dan Sinclair69472872015-10-28 10:20:35 -0400458 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700459 m_Pos--;
460 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700461 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700462 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700463}
Dan Sinclair69472872015-10-28 10:20:35 -0400464
Ryan Harrison275e2602017-09-18 14:23:18 -0400465ByteString CPDF_StreamParser::ReadString() {
Dan Sinclair90c90052015-10-28 13:05:52 -0400466 if (!PositionIsInBounds())
Ryan Harrison275e2602017-09-18 14:23:18 -0400467 return ByteString();
Dan Sinclair90c90052015-10-28 13:05:52 -0400468
Dan Sinclair1c915372016-03-03 17:12:58 -0500469 uint8_t ch = m_pBuf[m_Pos++];
Henrique Nakashima09150872017-06-08 10:08:08 -0400470 std::ostringstream buf;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700471 int parlevel = 0;
Dan Sinclair1c915372016-03-03 17:12:58 -0500472 int status = 0;
473 int iEscCode = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700474 while (1) {
475 switch (status) {
476 case 0:
477 if (ch == ')') {
478 if (parlevel == 0) {
Henrique Nakashimaaa1c7872018-01-30 19:12:10 +0000479 if (buf.tellp() <= 0)
480 return ByteString();
481
Ryan Harrison875e98c2017-09-27 10:53:11 -0400482 return ByteString(
483 buf.str().c_str(),
484 std::min(static_cast<size_t>(buf.tellp()), kMaxStringLength));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700485 }
486 parlevel--;
Henrique Nakashima09150872017-06-08 10:08:08 -0400487 buf << ')';
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700488 } else if (ch == '(') {
489 parlevel++;
Henrique Nakashima09150872017-06-08 10:08:08 -0400490 buf << '(';
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700491 } else if (ch == '\\') {
492 status = 1;
493 } else {
Henrique Nakashima09150872017-06-08 10:08:08 -0400494 buf << static_cast<char>(ch);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700495 }
496 break;
497 case 1:
498 if (ch >= '0' && ch <= '7') {
Lei Zhange8c1d412017-05-04 12:13:55 -0700499 iEscCode = FXSYS_DecimalCharToInt(static_cast<char>(ch));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700500 status = 2;
501 break;
502 }
Lei Zhangb8d86802017-12-01 22:52:42 +0000503 if (ch == '\r') {
504 status = 4;
505 break;
506 }
507 if (ch == '\n') {
508 // Do nothing.
509 } else if (ch == 'n') {
Henrique Nakashima09150872017-06-08 10:08:08 -0400510 buf << '\n';
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700511 } else if (ch == 'r') {
Henrique Nakashima09150872017-06-08 10:08:08 -0400512 buf << '\r';
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700513 } else if (ch == 't') {
Henrique Nakashima09150872017-06-08 10:08:08 -0400514 buf << '\t';
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700515 } else if (ch == 'b') {
Henrique Nakashima09150872017-06-08 10:08:08 -0400516 buf << '\b';
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517 } else if (ch == 'f') {
Henrique Nakashima09150872017-06-08 10:08:08 -0400518 buf << '\f';
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700519 } else {
Henrique Nakashima09150872017-06-08 10:08:08 -0400520 buf << static_cast<char>(ch);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700521 }
522 status = 0;
523 break;
524 case 2:
525 if (ch >= '0' && ch <= '7') {
Dan Sinclair1c915372016-03-03 17:12:58 -0500526 iEscCode =
Lei Zhange8c1d412017-05-04 12:13:55 -0700527 iEscCode * 8 + FXSYS_DecimalCharToInt(static_cast<char>(ch));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700528 status = 3;
529 } else {
Henrique Nakashima09150872017-06-08 10:08:08 -0400530 buf << static_cast<char>(iEscCode);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700531 status = 0;
532 continue;
533 }
534 break;
535 case 3:
536 if (ch >= '0' && ch <= '7') {
Dan Sinclair1c915372016-03-03 17:12:58 -0500537 iEscCode =
Lei Zhange8c1d412017-05-04 12:13:55 -0700538 iEscCode * 8 + FXSYS_DecimalCharToInt(static_cast<char>(ch));
Henrique Nakashima09150872017-06-08 10:08:08 -0400539 buf << static_cast<char>(iEscCode);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700540 status = 0;
541 } else {
Henrique Nakashima09150872017-06-08 10:08:08 -0400542 buf << static_cast<char>(iEscCode);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700543 status = 0;
544 continue;
545 }
546 break;
547 case 4:
548 status = 0;
Henrique Nakashima09150872017-06-08 10:08:08 -0400549 if (ch != '\n')
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700550 continue;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700551 break;
552 }
Dan Sinclair90c90052015-10-28 13:05:52 -0400553 if (!PositionIsInBounds())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700554 break;
Dan Sinclair90c90052015-10-28 13:05:52 -0400555
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700556 ch = m_pBuf[m_Pos++];
557 }
Dan Sinclair90c90052015-10-28 13:05:52 -0400558 if (PositionIsInBounds())
Dan Sinclair1c915372016-03-03 17:12:58 -0500559 ++m_Pos;
Dan Sinclair90c90052015-10-28 13:05:52 -0400560
Henrique Nakashimaaa1c7872018-01-30 19:12:10 +0000561 if (buf.tellp() <= 0)
562 return ByteString();
563
Ryan Harrison275e2602017-09-18 14:23:18 -0400564 return ByteString(
Henrique Nakashima09150872017-06-08 10:08:08 -0400565 buf.str().c_str(),
Ryan Harrison875e98c2017-09-27 10:53:11 -0400566 std::min(static_cast<size_t>(buf.tellp()), kMaxStringLength));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700567}
Wei Lidc4d5042016-01-19 13:19:44 -0800568
Ryan Harrison275e2602017-09-18 14:23:18 -0400569ByteString CPDF_StreamParser::ReadHexString() {
Dan Sinclair90c90052015-10-28 13:05:52 -0400570 if (!PositionIsInBounds())
Ryan Harrison275e2602017-09-18 14:23:18 -0400571 return ByteString();
Dan Sinclair90c90052015-10-28 13:05:52 -0400572
Henrique Nakashima09150872017-06-08 10:08:08 -0400573 std::ostringstream buf;
Dan Sinclair10cfea12015-11-16 13:09:00 -0500574 bool bFirst = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700575 int code = 0;
Dan Sinclair10cfea12015-11-16 13:09:00 -0500576 while (PositionIsInBounds()) {
577 int ch = m_pBuf[m_Pos++];
578
579 if (ch == '>')
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700580 break;
Dan Sinclair90c90052015-10-28 13:05:52 -0400581
Dan Sinclair10cfea12015-11-16 13:09:00 -0500582 if (!std::isxdigit(ch))
583 continue;
584
Lei Zhange8c1d412017-05-04 12:13:55 -0700585 int val = FXSYS_HexCharToInt(ch);
Dan Sinclair10cfea12015-11-16 13:09:00 -0500586 if (bFirst) {
587 code = val * 16;
588 } else {
589 code += val;
Henrique Nakashima09150872017-06-08 10:08:08 -0400590 buf << static_cast<uint8_t>(code);
Dan Sinclair10cfea12015-11-16 13:09:00 -0500591 }
592 bFirst = !bFirst;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700593 }
Dan Sinclair10cfea12015-11-16 13:09:00 -0500594 if (!bFirst)
Henrique Nakashima09150872017-06-08 10:08:08 -0400595 buf << static_cast<char>(code);
Dan Sinclair10cfea12015-11-16 13:09:00 -0500596
Henrique Nakashimaaa1c7872018-01-30 19:12:10 +0000597 if (buf.tellp() <= 0)
598 return ByteString();
599
Ryan Harrison275e2602017-09-18 14:23:18 -0400600 return ByteString(
Henrique Nakashima09150872017-06-08 10:08:08 -0400601 buf.str().c_str(),
Ryan Harrison875e98c2017-09-27 10:53:11 -0400602 std::min(static_cast<size_t>(buf.tellp()), kMaxStringLength));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700603}
Dan Sinclair90c90052015-10-28 13:05:52 -0400604
605bool CPDF_StreamParser::PositionIsInBounds() const {
Tom Sepez6058efd2018-04-06 23:48:24 +0000606 return m_Pos < m_pBuf.size();
Dan Sinclair90c90052015-10-28 13:05:52 -0400607}