| 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" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 m_DirectObjTypes = { | 84 m_DirectObjTypes = { |
| 85 CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER, | 85 CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER, |
| 86 CPDF_Object::NUMBER, CPDF_Object::STRING, CPDF_Object::STRING, | 86 CPDF_Object::NUMBER, CPDF_Object::STRING, CPDF_Object::STRING, |
| 87 CPDF_Object::NAME, CPDF_Object::ARRAY, CPDF_Object::DICTIONARY, | 87 CPDF_Object::NAME, CPDF_Object::ARRAY, CPDF_Object::DICTIONARY, |
| 88 CPDF_Object::STREAM, CPDF_Object::NULLOBJ}; | 88 CPDF_Object::STREAM, CPDF_Object::NULLOBJ}; |
| 89 for (size_t i = 0; i < FX_ArraySize(objs); ++i) | 89 for (size_t i = 0; i < FX_ArraySize(objs); ++i) |
| 90 m_DirectObjs.emplace_back(objs[i]); | 90 m_DirectObjs.emplace_back(objs[i]); |
| 91 | 91 |
| 92 // Indirect references to indirect objects. | 92 // Indirect references to indirect objects. |
| 93 m_ObjHolder.reset(new CPDF_IndirectObjectHolder()); | 93 m_ObjHolder.reset(new CPDF_IndirectObjectHolder()); |
| 94 m_IndirectObjs = {boolean_true_obj->Clone(), number_int_obj->Clone(), | 94 m_IndirectObjs = { |
| 95 str_spec_obj->Clone(), name_obj->Clone(), | 95 boolean_true_obj->Clone().release(), number_int_obj->Clone().release(), |
| 96 m_ArrayObj->Clone(), m_DictObj->Clone(), | 96 str_spec_obj->Clone().release(), name_obj->Clone().release(), |
| 97 stream_obj->Clone()}; | 97 m_ArrayObj->Clone().release(), m_DictObj->Clone().release(), |
| 98 stream_obj->Clone().release()}; |
| 98 for (size_t i = 0; i < m_IndirectObjs.size(); ++i) { | 99 for (size_t i = 0; i < m_IndirectObjs.size(); ++i) { |
| 99 m_ObjHolder->AddIndirectObject(m_IndirectObjs[i]); | 100 m_ObjHolder->AddIndirectObject(m_IndirectObjs[i]); |
| 100 m_RefObjs.emplace_back(new CPDF_Reference( | 101 m_RefObjs.emplace_back(new CPDF_Reference( |
| 101 m_ObjHolder.get(), m_IndirectObjs[i]->GetObjNum())); | 102 m_ObjHolder.get(), m_IndirectObjs[i]->GetObjNum())); |
| 102 } | 103 } |
| 103 } | 104 } |
| 104 | 105 |
| 105 bool Equal(const CPDF_Object* obj1, const CPDF_Object* obj2) { | 106 bool Equal(const CPDF_Object* obj1, const CPDF_Object* obj2) { |
| 106 if (obj1 == obj2) | 107 if (obj1 == obj2) |
| 107 return true; | 108 return true; |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->AsArray()); | 262 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->AsArray()); |
| 262 | 263 |
| 263 // Check indirect references. | 264 // Check indirect references. |
| 264 for (const auto& it : m_RefObjs) | 265 for (const auto& it : m_RefObjs) |
| 265 EXPECT_EQ(nullptr, it->AsArray()); | 266 EXPECT_EQ(nullptr, it->AsArray()); |
| 266 } | 267 } |
| 267 | 268 |
| 268 TEST_F(PDFObjectsTest, Clone) { | 269 TEST_F(PDFObjectsTest, Clone) { |
| 269 // Check for direct objects. | 270 // Check for direct objects. |
| 270 for (size_t i = 0; i < m_DirectObjs.size(); ++i) { | 271 for (size_t i = 0; i < m_DirectObjs.size(); ++i) { |
| 271 std::unique_ptr<CPDF_Object> obj(m_DirectObjs[i]->Clone()); | 272 std::unique_ptr<CPDF_Object> obj = m_DirectObjs[i]->Clone(); |
| 272 EXPECT_TRUE(Equal(m_DirectObjs[i].get(), obj.get())); | 273 EXPECT_TRUE(Equal(m_DirectObjs[i].get(), obj.get())); |
| 273 } | 274 } |
| 274 | 275 |
| 275 // Check indirect references. | 276 // Check indirect references. |
| 276 for (const auto& it : m_RefObjs) { | 277 for (const auto& it : m_RefObjs) { |
| 277 std::unique_ptr<CPDF_Object> obj(it->Clone()); | 278 std::unique_ptr<CPDF_Object> obj = it->Clone(); |
| 278 EXPECT_TRUE(Equal(it.get(), obj.get())); | 279 EXPECT_TRUE(Equal(it.get(), obj.get())); |
| 279 } | 280 } |
| 280 } | 281 } |
| 281 | 282 |
| 282 TEST_F(PDFObjectsTest, GetType) { | 283 TEST_F(PDFObjectsTest, GetType) { |
| 283 // Check for direct objects. | 284 // Check for direct objects. |
| 284 for (size_t i = 0; i < m_DirectObjs.size(); ++i) | 285 for (size_t i = 0; i < m_DirectObjs.size(); ++i) |
| 285 EXPECT_EQ(m_DirectObjTypes[i], m_DirectObjs[i]->GetType()); | 286 EXPECT_EQ(m_DirectObjTypes[i], m_DirectObjs[i]->GetType()); |
| 286 | 287 |
| 287 // Check indirect references. | 288 // Check indirect references. |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 | 745 |
| 745 TEST(PDFArrayTest, CloneDirectObject) { | 746 TEST(PDFArrayTest, CloneDirectObject) { |
| 746 CPDF_IndirectObjectHolder objects_holder; | 747 CPDF_IndirectObjectHolder objects_holder; |
| 747 std::unique_ptr<CPDF_Array> array(new CPDF_Array); | 748 std::unique_ptr<CPDF_Array> array(new CPDF_Array); |
| 748 array->AddReference(&objects_holder, 1234); | 749 array->AddReference(&objects_holder, 1234); |
| 749 ASSERT_EQ(1U, array->GetCount()); | 750 ASSERT_EQ(1U, array->GetCount()); |
| 750 CPDF_Object* obj = array->GetObjectAt(0); | 751 CPDF_Object* obj = array->GetObjectAt(0); |
| 751 ASSERT_TRUE(obj); | 752 ASSERT_TRUE(obj); |
| 752 EXPECT_TRUE(obj->IsReference()); | 753 EXPECT_TRUE(obj->IsReference()); |
| 753 | 754 |
| 754 CPDF_Object* cloned_array_object = array->CloneDirectObject(); | 755 std::unique_ptr<CPDF_Object> cloned_array_object = array->CloneDirectObject(); |
| 755 ASSERT_TRUE(cloned_array_object); | 756 ASSERT_TRUE(cloned_array_object); |
| 756 ASSERT_TRUE(cloned_array_object->IsArray()); | 757 ASSERT_TRUE(cloned_array_object->IsArray()); |
| 757 | 758 |
| 758 std::unique_ptr<CPDF_Array> cloned_array(cloned_array_object->AsArray()); | 759 std::unique_ptr<CPDF_Array> cloned_array = |
| 760 ToArray(std::move(cloned_array_object)); |
| 759 ASSERT_EQ(1U, cloned_array->GetCount()); | 761 ASSERT_EQ(1U, cloned_array->GetCount()); |
| 760 CPDF_Object* cloned_obj = cloned_array->GetObjectAt(0); | 762 CPDF_Object* cloned_obj = cloned_array->GetObjectAt(0); |
| 761 EXPECT_FALSE(cloned_obj); | 763 EXPECT_FALSE(cloned_obj); |
| 762 } | 764 } |
| 763 | 765 |
| 764 TEST(PDFArrayTest, ConvertIndirect) { | 766 TEST(PDFArrayTest, ConvertIndirect) { |
| 765 CPDF_IndirectObjectHolder objects_holder; | 767 CPDF_IndirectObjectHolder objects_holder; |
| 766 std::unique_ptr<CPDF_Array> array(new CPDF_Array); | 768 std::unique_ptr<CPDF_Array> array(new CPDF_Array); |
| 767 CPDF_Object* pObj = new CPDF_Number(42); | 769 CPDF_Object* pObj = new CPDF_Number(42); |
| 768 array->Add(pObj); | 770 array->Add(pObj); |
| 769 array->ConvertToIndirectObjectAt(0, &objects_holder); | 771 array->ConvertToIndirectObjectAt(0, &objects_holder); |
| 770 CPDF_Object* pRef = array->GetObjectAt(0); | 772 CPDF_Object* pRef = array->GetObjectAt(0); |
| 771 CPDF_Object* pNum = array->GetDirectObjectAt(0); | 773 CPDF_Object* pNum = array->GetDirectObjectAt(0); |
| 772 EXPECT_TRUE(pRef->IsReference()); | 774 EXPECT_TRUE(pRef->IsReference()); |
| 773 EXPECT_TRUE(pNum->IsNumber()); | 775 EXPECT_TRUE(pNum->IsNumber()); |
| 774 EXPECT_NE(pObj, pRef); | 776 EXPECT_NE(pObj, pRef); |
| 775 EXPECT_EQ(pObj, pNum); | 777 EXPECT_EQ(pObj, pNum); |
| 776 EXPECT_EQ(42, array->GetIntegerAt(0)); | 778 EXPECT_EQ(42, array->GetIntegerAt(0)); |
| 777 } | 779 } |
| 778 | 780 |
| 779 TEST(PDFDictionaryTest, CloneDirectObject) { | 781 TEST(PDFDictionaryTest, CloneDirectObject) { |
| 780 CPDF_IndirectObjectHolder objects_holder; | 782 CPDF_IndirectObjectHolder objects_holder; |
| 781 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary()); | 783 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary()); |
| 782 dict->SetReferenceFor("foo", &objects_holder, 1234); | 784 dict->SetReferenceFor("foo", &objects_holder, 1234); |
| 783 ASSERT_EQ(1U, dict->GetCount()); | 785 ASSERT_EQ(1U, dict->GetCount()); |
| 784 CPDF_Object* obj = dict->GetObjectFor("foo"); | 786 CPDF_Object* obj = dict->GetObjectFor("foo"); |
| 785 ASSERT_TRUE(obj); | 787 ASSERT_TRUE(obj); |
| 786 EXPECT_TRUE(obj->IsReference()); | 788 EXPECT_TRUE(obj->IsReference()); |
| 787 | 789 |
| 788 CPDF_Object* cloned_dict_object = dict->CloneDirectObject(); | 790 std::unique_ptr<CPDF_Object> cloned_dict_object = dict->CloneDirectObject(); |
| 789 ASSERT_TRUE(cloned_dict_object); | 791 ASSERT_TRUE(cloned_dict_object); |
| 790 ASSERT_TRUE(cloned_dict_object->IsDictionary()); | 792 ASSERT_TRUE(cloned_dict_object->IsDictionary()); |
| 791 | 793 |
| 792 std::unique_ptr<CPDF_Dictionary> cloned_dict( | 794 std::unique_ptr<CPDF_Dictionary> cloned_dict = |
| 793 cloned_dict_object->AsDictionary()); | 795 ToDictionary(std::move(cloned_dict_object)); |
| 794 ASSERT_EQ(1U, cloned_dict->GetCount()); | 796 ASSERT_EQ(1U, cloned_dict->GetCount()); |
| 795 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); | 797 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); |
| 796 EXPECT_FALSE(cloned_obj); | 798 EXPECT_FALSE(cloned_obj); |
| 797 } | 799 } |
| 798 | 800 |
| 799 TEST(PDFObjectTest, CloneCheckLoop) { | 801 TEST(PDFObjectTest, CloneCheckLoop) { |
| 800 { | 802 { |
| 801 // Create a dictionary/array pair with a reference loop. | 803 // Create a dictionary/array pair with a reference loop. |
| 802 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); | 804 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); |
| 803 std::unique_ptr<CPDF_Array> arr_obj(new CPDF_Array); | 805 std::unique_ptr<CPDF_Array> arr_obj(new CPDF_Array); |
| 804 dict_obj->SetFor("arr", arr_obj.get()); | 806 dict_obj->SetFor("arr", arr_obj.get()); |
| 805 arr_obj->InsertAt(0, dict_obj); | 807 arr_obj->InsertAt(0, dict_obj); |
| 806 | 808 |
| 807 // Clone this object to see whether stack overflow will be triggered. | 809 // Clone this object to see whether stack overflow will be triggered. |
| 808 std::unique_ptr<CPDF_Array> cloned_array(arr_obj->Clone()->AsArray()); | 810 std::unique_ptr<CPDF_Array> cloned_array = ToArray(arr_obj->Clone()); |
| 809 // Cloned object should be the same as the original. | 811 // Cloned object should be the same as the original. |
| 810 ASSERT_TRUE(cloned_array); | 812 ASSERT_TRUE(cloned_array); |
| 811 EXPECT_EQ(1u, cloned_array->GetCount()); | 813 EXPECT_EQ(1u, cloned_array->GetCount()); |
| 812 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0); | 814 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0); |
| 813 ASSERT_TRUE(cloned_dict); | 815 ASSERT_TRUE(cloned_dict); |
| 814 ASSERT_TRUE(cloned_dict->IsDictionary()); | 816 ASSERT_TRUE(cloned_dict->IsDictionary()); |
| 815 // Recursively referenced object is not cloned. | 817 // Recursively referenced object is not cloned. |
| 816 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr")); | 818 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr")); |
| 817 } | 819 } |
| 818 { | 820 { |
| 819 // Create a dictionary/stream pair with a reference loop. | 821 // Create a dictionary/stream pair with a reference loop. |
| 820 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); | 822 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); |
| 821 std::unique_ptr<CPDF_Stream> stream_obj( | 823 std::unique_ptr<CPDF_Stream> stream_obj( |
| 822 new CPDF_Stream(nullptr, 0, dict_obj)); | 824 new CPDF_Stream(nullptr, 0, dict_obj)); |
| 823 dict_obj->SetFor("stream", stream_obj.get()); | 825 dict_obj->SetFor("stream", stream_obj.get()); |
| 824 | 826 |
| 825 // Clone this object to see whether stack overflow will be triggered. | 827 // Clone this object to see whether stack overflow will be triggered. |
| 826 std::unique_ptr<CPDF_Stream> cloned_stream(stream_obj->Clone()->AsStream()); | 828 std::unique_ptr<CPDF_Stream> cloned_stream = ToStream(stream_obj->Clone()); |
| 827 // Cloned object should be the same as the original. | 829 // Cloned object should be the same as the original. |
| 828 ASSERT_TRUE(cloned_stream); | 830 ASSERT_TRUE(cloned_stream); |
| 829 CPDF_Object* cloned_dict = cloned_stream->GetDict(); | 831 CPDF_Object* cloned_dict = cloned_stream->GetDict(); |
| 830 ASSERT_TRUE(cloned_dict); | 832 ASSERT_TRUE(cloned_dict); |
| 831 ASSERT_TRUE(cloned_dict->IsDictionary()); | 833 ASSERT_TRUE(cloned_dict->IsDictionary()); |
| 832 // Recursively referenced object is not cloned. | 834 // Recursively referenced object is not cloned. |
| 833 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream")); | 835 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream")); |
| 834 } | 836 } |
| 835 { | 837 { |
| 836 CPDF_IndirectObjectHolder objects_holder; | 838 CPDF_IndirectObjectHolder objects_holder; |
| 837 // Create an object with a reference loop. | 839 // Create an object with a reference loop. |
| 838 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); | 840 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); |
| 839 CPDF_Array* arr_obj = new CPDF_Array; | 841 CPDF_Array* arr_obj = new CPDF_Array; |
| 840 objects_holder.AddIndirectObject(dict_obj); | 842 objects_holder.AddIndirectObject(dict_obj); |
| 841 EXPECT_EQ(1u, dict_obj->GetObjNum()); | 843 EXPECT_EQ(1u, dict_obj->GetObjNum()); |
| 842 dict_obj->SetFor("arr", arr_obj); | 844 dict_obj->SetFor("arr", arr_obj); |
| 843 arr_obj->InsertAt( | 845 arr_obj->InsertAt( |
| 844 0, new CPDF_Reference(&objects_holder, dict_obj->GetObjNum())); | 846 0, new CPDF_Reference(&objects_holder, dict_obj->GetObjNum())); |
| 845 CPDF_Object* elem0 = arr_obj->GetObjectAt(0); | 847 CPDF_Object* elem0 = arr_obj->GetObjectAt(0); |
| 846 ASSERT_TRUE(elem0); | 848 ASSERT_TRUE(elem0); |
| 847 ASSERT_TRUE(elem0->IsReference()); | 849 ASSERT_TRUE(elem0->IsReference()); |
| 848 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum()); | 850 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum()); |
| 849 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect()); | 851 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect()); |
| 850 | 852 |
| 851 // Clone this object to see whether stack overflow will be triggered. | 853 // Clone this object to see whether stack overflow will be triggered. |
| 852 std::unique_ptr<CPDF_Dictionary> cloned_dict( | 854 std::unique_ptr<CPDF_Dictionary> cloned_dict = |
| 853 ToDictionary(dict_obj->CloneDirectObject())); | 855 ToDictionary(dict_obj->CloneDirectObject()); |
| 854 // Cloned object should be the same as the original. | 856 // Cloned object should be the same as the original. |
| 855 ASSERT_TRUE(cloned_dict); | 857 ASSERT_TRUE(cloned_dict); |
| 856 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); | 858 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); |
| 857 ASSERT_TRUE(cloned_arr); | 859 ASSERT_TRUE(cloned_arr); |
| 858 ASSERT_TRUE(cloned_arr->IsArray()); | 860 ASSERT_TRUE(cloned_arr->IsArray()); |
| 859 EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); | 861 EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); |
| 860 // Recursively referenced object is not cloned. | 862 // Recursively referenced object is not cloned. |
| 861 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); | 863 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); |
| 862 } | 864 } |
| 863 } | 865 } |
| 864 | 866 |
| 865 TEST(PDFDictionaryTest, ConvertIndirect) { | 867 TEST(PDFDictionaryTest, ConvertIndirect) { |
| 866 CPDF_IndirectObjectHolder objects_holder; | 868 CPDF_IndirectObjectHolder objects_holder; |
| 867 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary); | 869 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary); |
| 868 CPDF_Object* pObj = new CPDF_Number(42); | 870 CPDF_Object* pObj = new CPDF_Number(42); |
| 869 dict->SetFor("clams", pObj); | 871 dict->SetFor("clams", pObj); |
| 870 dict->ConvertToIndirectObjectFor("clams", &objects_holder); | 872 dict->ConvertToIndirectObjectFor("clams", &objects_holder); |
| 871 CPDF_Object* pRef = dict->GetObjectFor("clams"); | 873 CPDF_Object* pRef = dict->GetObjectFor("clams"); |
| 872 CPDF_Object* pNum = dict->GetDirectObjectFor("clams"); | 874 CPDF_Object* pNum = dict->GetDirectObjectFor("clams"); |
| 873 EXPECT_TRUE(pRef->IsReference()); | 875 EXPECT_TRUE(pRef->IsReference()); |
| 874 EXPECT_TRUE(pNum->IsNumber()); | 876 EXPECT_TRUE(pNum->IsNumber()); |
| 875 EXPECT_NE(pObj, pRef); | 877 EXPECT_NE(pObj, pRef); |
| 876 EXPECT_EQ(pObj, pNum); | 878 EXPECT_EQ(pObj, pNum); |
| 877 EXPECT_EQ(42, dict->GetIntegerFor("clams")); | 879 EXPECT_EQ(42, dict->GetIntegerFor("clams")); |
| 878 } | 880 } |
| OLD | NEW |