1// Copyright 2017 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#include "core/fpdfapi/parser/cpdf_cross_ref_avail.h" 6 7#include <memory> 8#include <string> 9 10#include "core/fpdfapi/parser/cpdf_syntax_parser.h" 11#include "testing/fx_string_testhelpers.h" 12#include "testing/gtest/include/gtest/gtest.h" 13#include "third_party/base/ptr_util.h" 14 15namespace { 16 17std::unique_ptr<CPDF_SyntaxParser> MakeParserForBuffer( 18 const unsigned char* buffer, 19 size_t buffer_size) { 20 auto parser = pdfium::MakeUnique<CPDF_SyntaxParser>(); 21 parser->InitParser( 22 pdfium::MakeRetain<CFX_BufferSeekableReadStream>(buffer, buffer_size), 0); 23 return parser; 24} 25 26} // namespace 27 28TEST(CPDF_CrossRefAvailTest, CheckCrossRefV4) { 29 const unsigned char xref_table[] = 30 "xref \n" 31 "0 6 \n" 32 "0000000003 65535 f \n" 33 "0000000017 00000 n \n" 34 "0000000081 00000 n \n" 35 "0000000000 00007 f \n" 36 "0000000331 00000 n \n" 37 "0000000409 00000 n \n" 38 "trailer\n" 39 "<</Root 14 0 R/ID " 40 "[<afbb0f593c2d2aea5b519cb61da1c17b><4f9bb2e7978401808f8f1f2a75c322c8>]" 41 "/Info 15 0 R/Size 16>>"; 42 const FX_FILESIZE last_crossref_offset = 0; 43 44 auto parser = MakeParserForBuffer(xref_table, FX_ArraySize(xref_table)); 45 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 46 parser.get(), last_crossref_offset); 47 48 EXPECT_EQ(CPDF_DataAvail::DataAvailable, cross_ref_avail->CheckAvail()); 49} 50 51TEST(CPDF_CrossRefAvailTest, CheckCrossRefStream) { 52 const unsigned char xref_stream[] = 53 "16 0 obj\n" 54 "<</Filter /FlateDecode>>" 55 " stream \n" 56 "STREAM DATA STREAM DATA STREAM DATA\n" 57 "endstream\n" 58 "endobj\n"; 59 const FX_FILESIZE last_crossref_offset = 0; 60 61 auto parser = MakeParserForBuffer(xref_stream, FX_ArraySize(xref_stream)); 62 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 63 parser.get(), last_crossref_offset); 64 65 EXPECT_EQ(CPDF_DataAvail::DataAvailable, cross_ref_avail->CheckAvail()); 66} 67 68TEST(CPDF_CrossRefAvailTest, IncorrectStartOffset) { 69 const unsigned char xref_stream[] = 70 "16 0 obj\n" 71 "<</Filter /FlateDecode>>" 72 " stream \n" 73 "STREAM DATA STREAM DATA STREAM DATA\n" 74 "endstream\n" 75 "endobj\n"; 76 77 const FX_FILESIZE last_crossref_offset = 70000; 78 79 auto parser = MakeParserForBuffer(xref_stream, FX_ArraySize(xref_stream)); 80 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 81 parser.get(), last_crossref_offset); 82 83 EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); 84} 85 86TEST(CPDF_CrossRefAvailTest, IncorrectPrevOffset) { 87 const unsigned char xref_stream[] = 88 "16 0 obj\n" 89 "<</Type /XRef /Prev 70000>>" 90 " stream \n" 91 "STREAM DATA STREAM DATA STREAM DATA\n" 92 "endstream\n" 93 "endobj\n"; 94 const FX_FILESIZE last_crossref_offset = 0; 95 96 auto parser = MakeParserForBuffer(xref_stream, FX_ArraySize(xref_stream)); 97 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 98 parser.get(), last_crossref_offset); 99 EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); 100} 101 102TEST(CPDF_CrossRefAvailTest, IncorrectPrevStreamOffset) { 103 const unsigned char xref_table[] = 104 "xref \n" 105 "0 6 \n" 106 "0000000003 65535 f \n" 107 "0000000017 00000 n \n" 108 "0000000081 00000 n \n" 109 "0000000000 00007 f \n" 110 "0000000331 00000 n \n" 111 "0000000409 00000 n \n" 112 "trailer\n" 113 "<</Root 14 0 R/ID " 114 "[<afbb0f593c2d2aea5b519cb61da1c17b><4f9bb2e7978401808f8f1f2a75c322c8>]" 115 "/Info 15 0 R/Size 16 /XRefStm 70000>>"; 116 const FX_FILESIZE last_crossref_offset = 0; 117 118 auto parser = MakeParserForBuffer(xref_table, FX_ArraySize(xref_table)); 119 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 120 parser.get(), last_crossref_offset); 121 EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); 122} 123 124TEST(CPDF_CrossRefAvailTest, IncorrectData) { 125 const unsigned char incorrect_data[] = 126 "fiajaoilf w9ifaoihwoiafhja wfijaofijoiaw fhj oiawhfoiah " 127 "wfoihoiwfghouiafghwoigahfi"; 128 const FX_FILESIZE last_crossref_offset = 0; 129 130 auto parser = 131 MakeParserForBuffer(incorrect_data, FX_ArraySize(incorrect_data)); 132 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 133 parser.get(), last_crossref_offset); 134 EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); 135} 136 137TEST(CPDF_CrossRefAvailTest, ThreeCrossRefV4) { 138 char int_buffer[100]; 139 int prev_offset = 0; 140 int cur_offset = 0; 141 std::string table = "pdf blah blah blah\n"; 142 prev_offset = cur_offset; 143 cur_offset = static_cast<int>(table.size()); 144 table += 145 "xref \n" 146 "0 6 \n" 147 "0000000003 65535 f \n" 148 "trailer\n" 149 "<</Root 14 0 R/ID " 150 "[<afbb0f593c2d2aea5b519cb61da1c17b><4f9bb2e7978401808f8f1f2a75c322c8>]" 151 "/Info 15 0 R/Size 16>>\n"; 152 table += "Dummy Data jgwhughouiwbahng"; 153 prev_offset = cur_offset; 154 cur_offset = static_cast<int>(table.size()); 155 table += std::string( 156 "xref \n" 157 "0 6 \n" 158 "0000000003 65535 f \n" 159 "trailer\n" 160 "<</Root 14 0 R/ID " 161 "[<afbb0f593c2d2aea5b519cb61da1c17b><" 162 "4f9bb2e7978401808f8f1f2a75c322c8>]" 163 "/Info 15 0 R/Size 16" 164 "/Prev ") + 165 FXSYS_itoa(prev_offset, int_buffer, 10) + ">>\n"; 166 table += "More Dummy Data jgwhughouiwbahng"; 167 prev_offset = cur_offset; 168 cur_offset = static_cast<int>(table.size()); 169 table += std::string( 170 "xref \n" 171 "0 6 \n" 172 "0000000003 65535 f \n" 173 "trailer\n" 174 "<</Root 14 0 R/ID " 175 "[<afbb0f593c2d2aea5b519cb61da1c17b><" 176 "4f9bb2e7978401808f8f1f2a75c322c8>]" 177 "/Info 15 0 R/Size 16" 178 "/Prev ") + 179 FXSYS_itoa(prev_offset, int_buffer, 10) + ">>\n"; 180 const FX_FILESIZE last_crossref_offset = cur_offset; 181 182 auto parser = MakeParserForBuffer( 183 reinterpret_cast<const unsigned char*>(table.data()), table.size()); 184 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 185 parser.get(), last_crossref_offset); 186 EXPECT_EQ(CPDF_DataAvail::DataAvailable, cross_ref_avail->CheckAvail()); 187} 188 189TEST(CPDF_CrossRefAvailTest, ThreeCrossRefV5) { 190 char int_buffer[100]; 191 int prev_offset = 0; 192 int cur_offset = 0; 193 std::string table = "pdf blah blah blah\n"; 194 prev_offset = cur_offset; 195 cur_offset = static_cast<int>(table.size()); 196 table += 197 "16 0 obj\n" 198 "<</Type /XRef>>" 199 " stream \n" 200 "STREAM DATA STREAM DATA STREAM DATA ahfcuabfkuabfu\n" 201 "endstream\n" 202 "endobj\n"; 203 table += "Dummy Data jgwhughouiwbahng"; 204 205 prev_offset = cur_offset; 206 cur_offset = static_cast<int>(table.size()); 207 table += std::string( 208 "55 0 obj\n" 209 "<</Type /XRef /Prev ") + 210 FXSYS_itoa(prev_offset, int_buffer, 10) + 211 ">>" 212 " stream \n" 213 "STREAM DATA STREAM DATA STREAM DATA\n" 214 "endstream\n" 215 "endobj\n"; 216 table += "More Dummy Data jgwhughouiwbahng"; 217 prev_offset = cur_offset; 218 cur_offset = static_cast<int>(table.size()); 219 table += std::string( 220 "88 0 obj\n" 221 "<</Type /XRef /NNNN /Prev ") + 222 FXSYS_itoa(prev_offset, int_buffer, 10) + 223 ">>" 224 " stream \n" 225 "STREAM DATA STREAM DATA STREAM DATA favav\n" 226 "endstream\n" 227 "endobj\n"; 228 const FX_FILESIZE last_crossref_offset = cur_offset; 229 230 auto parser = MakeParserForBuffer( 231 reinterpret_cast<const unsigned char*>(table.data()), table.size()); 232 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 233 parser.get(), last_crossref_offset); 234 EXPECT_EQ(CPDF_DataAvail::DataAvailable, cross_ref_avail->CheckAvail()); 235} 236 237TEST(CPDF_CrossRefAvailTest, Mixed) { 238 char int_buffer[100]; 239 std::string table = "pdf blah blah blah\n"; 240 241 const int first_v5_table_offset = static_cast<int>(table.size()); 242 table += 243 "16 0 obj\n" 244 "<</Type /XRef>>" 245 " stream \n" 246 "STREAM DATA STREAM DATA STREAM DATA ahfcuabfkuabfu\n" 247 "endstream\n" 248 "endobj\n"; 249 table += "Dummy Data jgwhughouiwbahng"; 250 251 const int second_v4_table_offset = static_cast<int>(table.size()); 252 table += std::string( 253 "xref \n" 254 "0 6 \n" 255 "0000000003 65535 f \n" 256 "trailer\n" 257 "<</Root 14 0 R/ID " 258 "[<afbb0f593c2d2aea5b519cb61da1c17b><" 259 "4f9bb2e7978401808f8f1f2a75c322c8>]" 260 "/Info 15 0 R/Size 16" 261 "/Prev ") + 262 FXSYS_itoa(first_v5_table_offset, int_buffer, 10) + ">>\n"; 263 table += "More Dummy Data jgwhughouiwbahng"; 264 265 const int last_v4_table_offset = static_cast<int>(table.size()); 266 table += std::string( 267 "xref \n" 268 "0 6 \n" 269 "0000000003 65535 f \n" 270 "trailer\n" 271 "<</Root 14 0 R/ID " 272 "[<afbb0f593c2d2aea5b519cb61da1c17b><" 273 "4f9bb2e7978401808f8f1f2a75c322c8>]" 274 "/Info 15 0 R/Size 16" 275 "/Prev ") + 276 FXSYS_itoa(second_v4_table_offset, int_buffer, 10) + " /XRefStm " + 277 FXSYS_itoa(first_v5_table_offset, int_buffer, 10) + ">>\n"; 278 const FX_FILESIZE last_crossref_offset = last_v4_table_offset; 279 280 auto parser = MakeParserForBuffer( 281 reinterpret_cast<const unsigned char*>(table.data()), table.size()); 282 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 283 parser.get(), last_crossref_offset); 284 EXPECT_EQ(CPDF_DataAvail::DataAvailable, cross_ref_avail->CheckAvail()); 285} 286 287TEST(CPDF_CrossRefAvailTest, CrossRefV5IsNotStream) { 288 const unsigned char invalid_xref_stream[] = 289 "16 0 obj\n" 290 "[/array /object]\n" 291 "endstream\n" 292 "endobj\n"; 293 const FX_FILESIZE last_crossref_offset = 0; 294 295 auto parser = MakeParserForBuffer(invalid_xref_stream, 296 FX_ArraySize(invalid_xref_stream)); 297 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 298 parser.get(), last_crossref_offset); 299 EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); 300} 301 302TEST(CPDF_CrossRefAvailTest, CrossRefV4WithEncryptRef) { 303 const unsigned char xref_table[] = 304 "xref \n" 305 "0 6 \n" 306 "0000000003 65535 f \n" 307 "0000000017 00000 n \n" 308 "0000000081 00000 n \n" 309 "0000000000 00007 f \n" 310 "0000000331 00000 n \n" 311 "0000000409 00000 n \n" 312 "trailer\n" 313 "<</Root 14 0 R/ID " 314 "[<afbb0f593c2d2aea5b519cb61da1c17b><4f9bb2e7978401808f8f1f2a75c322c8>]" 315 "/Encrypt 77 0 R" 316 "/Info 15 0 R/Size 16>>"; 317 const FX_FILESIZE last_crossref_offset = 0; 318 319 auto parser = MakeParserForBuffer(xref_table, FX_ArraySize(xref_table)); 320 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 321 parser.get(), last_crossref_offset); 322 EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); 323} 324 325TEST(CPDF_CrossRefAvailTest, CrossRefStreamWithEncryptRef) { 326 const unsigned char xref_stream[] = 327 "16 0 obj\n" 328 "<</Filter /FlateDecode /Encrypt 77 0 R>>" 329 " stream \n" 330 "STREAM DATA STREAM DATA STREAM DATA\n" 331 "endstream\n" 332 "endobj\n"; 333 const FX_FILESIZE last_crossref_offset = 0; 334 335 auto parser = MakeParserForBuffer(xref_stream, FX_ArraySize(xref_stream)); 336 auto cross_ref_avail = pdfium::MakeUnique<CPDF_CrossRefAvail>( 337 parser.get(), last_crossref_offset); 338 EXPECT_EQ(CPDF_DataAvail::DataError, cross_ref_avail->CheckAvail()); 339} 340