| OLD | NEW | 
|    1 // Copyright 2016 PDFium Authors. All rights reserved. |    1 // Copyright 2016 PDFium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "core/fpdfapi/parser/cpdf_array.h" |    5 #include "core/fpdfapi/parser/cpdf_array.h" | 
|    6 #include "core/fpdfapi/parser/cpdf_boolean.h" |    6 #include "core/fpdfapi/parser/cpdf_boolean.h" | 
|    7 #include "core/fpdfapi/parser/cpdf_dictionary.h" |    7 #include "core/fpdfapi/parser/cpdf_dictionary.h" | 
|    8 #include "core/fpdfapi/parser/cpdf_name.h" |    8 #include "core/fpdfapi/parser/cpdf_name.h" | 
|    9 #include "core/fpdfapi/parser/cpdf_null.h" |    9 #include "core/fpdfapi/parser/cpdf_null.h" | 
|   10 #include "core/fpdfapi/parser/cpdf_number.h" |   10 #include "core/fpdfapi/parser/cpdf_number.h" | 
|   11 #include "core/fpdfapi/parser/cpdf_reference.h" |   11 #include "core/fpdfapi/parser/cpdf_reference.h" | 
|   12 #include "core/fpdfapi/parser/cpdf_stream.h" |   12 #include "core/fpdfapi/parser/cpdf_stream.h" | 
|   13 #include "core/fpdfapi/parser/cpdf_string.h" |   13 #include "core/fpdfapi/parser/cpdf_string.h" | 
|   14  |   14  | 
|   15 #include <memory> |   15 #include <memory> | 
|   16 #include <string> |   16 #include <string> | 
|   17 #include <vector> |   17 #include <vector> | 
|   18  |   18  | 
|   19 #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" |   19 #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" | 
|   20 #include "core/fxcrt/fx_basic.h" |   20 #include "core/fxcrt/fx_basic.h" | 
|   21 #include "testing/gtest/include/gtest/gtest.h" |   21 #include "testing/gtest/include/gtest/gtest.h" | 
|   22  |   22  | 
|   23 namespace { |   23 namespace { | 
|   24  |   24  | 
|   25 using ScopedArray = std::unique_ptr<CPDF_Array, ReleaseDeleter<CPDF_Array>>; |   25 using ScopedArray = std::unique_ptr<CPDF_Array, ReleaseDeleter<CPDF_Array>>; | 
|   26 using ScopedDict = |   26 using ScopedDict = | 
|   27     std::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>>; |   27     std::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>>; | 
|   28 using ScopedStream = std::unique_ptr<CPDF_Stream, ReleaseDeleter<CPDF_Stream>>; |  | 
|   29  |   28  | 
|   30 void TestArrayAccessors(const CPDF_Array* arr, |   29 void TestArrayAccessors(const CPDF_Array* arr, | 
|   31                         size_t index, |   30                         size_t index, | 
|   32                         const char* str_val, |   31                         const char* str_val, | 
|   33                         const char* const_str_val, |   32                         const char* const_str_val, | 
|   34                         int int_val, |   33                         int int_val, | 
|   35                         float float_val, |   34                         float float_val, | 
|   36                         CPDF_Array* arr_val, |   35                         CPDF_Array* arr_val, | 
|   37                         CPDF_Dictionary* dict_val, |   36                         CPDF_Dictionary* dict_val, | 
|   38                         CPDF_Stream* stream_val) { |   37                         CPDF_Stream* stream_val) { | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   89     m_DirectObjTypes = { |   88     m_DirectObjTypes = { | 
|   90         CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER, |   89         CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER, | 
|   91         CPDF_Object::NUMBER,  CPDF_Object::STRING,  CPDF_Object::STRING, |   90         CPDF_Object::NUMBER,  CPDF_Object::STRING,  CPDF_Object::STRING, | 
|   92         CPDF_Object::NAME,    CPDF_Object::ARRAY,   CPDF_Object::DICTIONARY, |   91         CPDF_Object::NAME,    CPDF_Object::ARRAY,   CPDF_Object::DICTIONARY, | 
|   93         CPDF_Object::STREAM,  CPDF_Object::NULLOBJ}; |   92         CPDF_Object::STREAM,  CPDF_Object::NULLOBJ}; | 
|   94     for (size_t i = 0; i < FX_ArraySize(objs); ++i) |   93     for (size_t i = 0; i < FX_ArraySize(objs); ++i) | 
|   95       m_DirectObjs.emplace_back(objs[i]); |   94       m_DirectObjs.emplace_back(objs[i]); | 
|   96  |   95  | 
|   97     // Indirect references to indirect objects. |   96     // Indirect references to indirect objects. | 
|   98     m_ObjHolder.reset(new CPDF_IndirectObjectHolder()); |   97     m_ObjHolder.reset(new CPDF_IndirectObjectHolder()); | 
|   99     m_IndirectObjs = {boolean_true_obj->Clone(), number_int_obj->Clone(), |   98     m_IndirectObjs = {boolean_true_obj, number_int_obj, str_spec_obj, name_obj, | 
|  100                       str_spec_obj->Clone(),     name_obj->Clone(), |   99                       m_ArrayObj,       m_DictObj,      stream_obj}; | 
|  101                       m_ArrayObj->Clone(),       m_DictObj->Clone(), |  | 
|  102                       stream_obj->Clone()}; |  | 
|  103     for (size_t i = 0; i < m_IndirectObjs.size(); ++i) { |  100     for (size_t i = 0; i < m_IndirectObjs.size(); ++i) { | 
|  104       m_ObjHolder->AddIndirectObject(m_IndirectObjs[i]); |  101       m_ObjHolder->AddIndirectObject(m_IndirectObjs[i]); | 
|  105       m_RefObjs.emplace_back(new CPDF_Reference( |  102       m_RefObjs.emplace_back(new CPDF_Reference( | 
|  106           m_ObjHolder.get(), m_IndirectObjs[i]->GetObjNum())); |  103           m_ObjHolder.get(), m_IndirectObjs[i]->GetObjNum())); | 
|  107     } |  104     } | 
|  108   } |  105   } | 
|  109  |  106  | 
|  110   bool Equal(const CPDF_Object* obj1, const CPDF_Object* obj2) { |  107   bool Equal(CPDF_Object* obj1, CPDF_Object* obj2) { | 
|  111     if (obj1 == obj2) |  108     if (obj1 == obj2) | 
|  112       return true; |  109       return true; | 
|  113     if (!obj1 || !obj2 || obj1->GetType() != obj2->GetType()) |  110     if (!obj1 || !obj2 || obj1->GetType() != obj2->GetType()) | 
|  114       return false; |  111       return false; | 
|  115     switch (obj1->GetType()) { |  112     switch (obj1->GetType()) { | 
|  116       case CPDF_Object::BOOLEAN: |  113       case CPDF_Object::BOOLEAN: | 
|  117         return obj1->GetInteger() == obj2->GetInteger(); |  114         return obj1->GetInteger() == obj2->GetInteger(); | 
|  118       case CPDF_Object::NUMBER: |  115       case CPDF_Object::NUMBER: | 
|  119         return obj1->AsNumber()->IsInteger() == obj2->AsNumber()->IsInteger() && |  116         return obj1->AsNumber()->IsInteger() == obj2->AsNumber()->IsInteger() && | 
|  120                obj1->GetInteger() == obj2->GetInteger(); |  117                obj1->GetInteger() == obj2->GetInteger(); | 
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  249       nullptr, nullptr, nullptr,   nullptr,         nullptr, nullptr, |  246       nullptr, nullptr, nullptr,   nullptr,         nullptr, nullptr, | 
|  250       nullptr, nullptr, m_DictObj, m_StreamDictObj, nullptr}; |  247       nullptr, nullptr, m_DictObj, m_StreamDictObj, nullptr}; | 
|  251   // Check for direct objects. |  248   // Check for direct objects. | 
|  252   for (size_t i = 0; i < m_DirectObjs.size(); ++i) |  249   for (size_t i = 0; i < m_DirectObjs.size(); ++i) | 
|  253     EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetDict()); |  250     EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetDict()); | 
|  254  |  251  | 
|  255   // Check indirect references. |  252   // Check indirect references. | 
|  256   const CPDF_Dictionary* const indirect_obj_results[] = { |  253   const CPDF_Dictionary* const indirect_obj_results[] = { | 
|  257       nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj, m_StreamDictObj}; |  254       nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj, m_StreamDictObj}; | 
|  258   for (size_t i = 0; i < m_RefObjs.size(); ++i) |  255   for (size_t i = 0; i < m_RefObjs.size(); ++i) | 
|  259     EXPECT_TRUE(Equal(indirect_obj_results[i], m_RefObjs[i]->GetDict())); |  256     EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetDict()); | 
|  260 } |  257 } | 
|  261  |  258  | 
|  262 TEST_F(PDFObjectsTest, GetArray) { |  259 TEST_F(PDFObjectsTest, GetArray) { | 
|  263   const CPDF_Array* const direct_obj_results[] = { |  260   const CPDF_Array* const direct_obj_results[] = { | 
|  264       nullptr, nullptr,    nullptr, nullptr, nullptr, nullptr, |  261       nullptr, nullptr,    nullptr, nullptr, nullptr, nullptr, | 
|  265       nullptr, m_ArrayObj, nullptr, nullptr, nullptr}; |  262       nullptr, m_ArrayObj, nullptr, nullptr, nullptr}; | 
|  266   // Check for direct objects. |  263   // Check for direct objects. | 
|  267   for (size_t i = 0; i < m_DirectObjs.size(); ++i) |  264   for (size_t i = 0; i < m_DirectObjs.size(); ++i) | 
|  268     EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->AsArray()); |  265     EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->AsArray()); | 
|  269  |  266  | 
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  783   ASSERT_TRUE(cloned_dict_object->IsDictionary()); |  780   ASSERT_TRUE(cloned_dict_object->IsDictionary()); | 
|  784  |  781  | 
|  785   ScopedDict cloned_dict(cloned_dict_object->AsDictionary()); |  782   ScopedDict cloned_dict(cloned_dict_object->AsDictionary()); | 
|  786   ASSERT_EQ(1U, cloned_dict->GetCount()); |  783   ASSERT_EQ(1U, cloned_dict->GetCount()); | 
|  787   CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); |  784   CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); | 
|  788   EXPECT_FALSE(cloned_obj); |  785   EXPECT_FALSE(cloned_obj); | 
|  789 } |  786 } | 
|  790  |  787  | 
|  791 TEST(PDFObjectTest, CloneCheckLoop) { |  788 TEST(PDFObjectTest, CloneCheckLoop) { | 
|  792   { |  789   { | 
|  793     // Create a dictionary/array pair with a reference loop. |  790     // Create an object with a reference loop. | 
 |  791     ScopedArray arr_obj(new CPDF_Array); | 
 |  792     // Dictionary object. | 
|  794     CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); |  793     CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); | 
|  795     ScopedArray arr_obj(new CPDF_Array); |  | 
|  796     dict_obj->SetFor("arr", arr_obj.get()); |  794     dict_obj->SetFor("arr", arr_obj.get()); | 
|  797     arr_obj->InsertAt(0, dict_obj); |  795     arr_obj->InsertAt(0, dict_obj); | 
|  798  |  796  | 
|  799     // Clone this object to see whether stack overflow will be triggered. |  797     // Clone this object to see whether stack overflow will be triggered. | 
|  800     ScopedArray cloned_array(arr_obj->Clone()->AsArray()); |  798     ScopedArray cloned_array(arr_obj->Clone()->AsArray()); | 
|  801     // Cloned object should be the same as the original. |  799     // Cloned object should be the same as the original. | 
|  802     ASSERT_TRUE(cloned_array); |  800     ASSERT_TRUE(cloned_array); | 
|  803     EXPECT_EQ(1u, cloned_array->GetCount()); |  801     EXPECT_EQ(1u, cloned_array->GetCount()); | 
|  804     CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0); |  802     CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0); | 
|  805     ASSERT_TRUE(cloned_dict); |  803     ASSERT_TRUE(cloned_dict); | 
|  806     ASSERT_TRUE(cloned_dict->IsDictionary()); |  804     ASSERT_TRUE(cloned_dict->IsDictionary()); | 
|  807     // Recursively referenced object is not cloned. |  805     // Recursively referenced object is not cloned. | 
|  808     EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr")); |  806     EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr")); | 
|  809   } |  807   } | 
|  810   { |  808   { | 
|  811     // Create a dictionary/stream pair with a reference loop. |  | 
|  812     CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); |  | 
|  813     ScopedStream stream_obj(new CPDF_Stream(nullptr, 0, dict_obj)); |  | 
|  814     dict_obj->SetFor("stream", stream_obj.get()); |  | 
|  815  |  | 
|  816     // Clone this object to see whether stack overflow will be triggered. |  | 
|  817     ScopedStream cloned_stream(stream_obj->Clone()->AsStream()); |  | 
|  818     // Cloned object should be the same as the original. |  | 
|  819     ASSERT_TRUE(cloned_stream); |  | 
|  820     CPDF_Object* cloned_dict = cloned_stream->GetDict(); |  | 
|  821     ASSERT_TRUE(cloned_dict); |  | 
|  822     ASSERT_TRUE(cloned_dict->IsDictionary()); |  | 
|  823     // Recursively referenced object is not cloned. |  | 
|  824     EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream")); |  | 
|  825   } |  | 
|  826   { |  | 
|  827     CPDF_IndirectObjectHolder objects_holder; |  809     CPDF_IndirectObjectHolder objects_holder; | 
|  828     // Create an object with a reference loop. |  810     // Create an object with a reference loop. | 
|  829     CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); |  811     CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); | 
|  830     CPDF_Array* arr_obj = new CPDF_Array; |  812     CPDF_Array* arr_obj = new CPDF_Array; | 
|  831     objects_holder.AddIndirectObject(dict_obj); |  813     objects_holder.AddIndirectObject(dict_obj); | 
|  832     EXPECT_EQ(1u, dict_obj->GetObjNum()); |  814     EXPECT_EQ(1u, dict_obj->GetObjNum()); | 
|  833     dict_obj->SetFor("arr", arr_obj); |  815     dict_obj->SetFor("arr", arr_obj); | 
|  834     arr_obj->InsertAt( |  816     arr_obj->InsertAt( | 
|  835         0, new CPDF_Reference(&objects_holder, dict_obj->GetObjNum())); |  817         0, new CPDF_Reference(&objects_holder, dict_obj->GetObjNum())); | 
|  836     CPDF_Object* elem0 = arr_obj->GetObjectAt(0); |  818     CPDF_Object* elem0 = arr_obj->GetObjectAt(0); | 
|  837     ASSERT_TRUE(elem0); |  819     ASSERT_TRUE(elem0); | 
|  838     ASSERT_TRUE(elem0->IsReference()); |  820     ASSERT_TRUE(elem0->IsReference()); | 
|  839     EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum()); |  821     EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum()); | 
|  840     EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect()); |  822     EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect()); | 
|  841  |  823  | 
|  842     // Clone this object to see whether stack overflow will be triggered. |  824     // Clone this object to see whether stack overflow will be triggered. | 
|  843     ScopedDict cloned_dict(ToDictionary(dict_obj->CloneDirectObject())); |  825     ScopedDict cloned_dict(ToDictionary(dict_obj->CloneDirectObject())); | 
|  844     // Cloned object should be the same as the original. |  826     // Cloned object should be the same as the original. | 
|  845     ASSERT_TRUE(cloned_dict); |  827     ASSERT_TRUE(cloned_dict); | 
|  846     CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); |  828     CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); | 
|  847     ASSERT_TRUE(cloned_arr); |  829     ASSERT_TRUE(cloned_arr); | 
|  848     ASSERT_TRUE(cloned_arr->IsArray()); |  830     ASSERT_TRUE(cloned_arr->IsArray()); | 
|  849     EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); |  831     EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); | 
|  850     // Recursively referenced object is not cloned. |  832     // Recursively referenced object is not cloned. | 
|  851     EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); |  833     EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); | 
|  852   } |  834   } | 
|  853 } |  835 } | 
| OLD | NEW |