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 <utility> |
17 #include <vector> | 18 #include <vector> |
18 | 19 |
19 #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" | 20 #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" |
20 #include "core/fxcrt/fx_basic.h" | 21 #include "core/fxcrt/fx_basic.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 void TestArrayAccessors(const CPDF_Array* arr, | 26 void TestArrayAccessors(const CPDF_Array* arr, |
26 size_t index, | 27 size_t index, |
(...skipping 19 matching lines...) Expand all Loading... |
46 public: | 47 public: |
47 void SetUp() override { | 48 void SetUp() override { |
48 // Initialize different kinds of objects. | 49 // Initialize different kinds of objects. |
49 // Boolean objects. | 50 // Boolean objects. |
50 CPDF_Boolean* boolean_false_obj = new CPDF_Boolean(false); | 51 CPDF_Boolean* boolean_false_obj = new CPDF_Boolean(false); |
51 CPDF_Boolean* boolean_true_obj = new CPDF_Boolean(true); | 52 CPDF_Boolean* boolean_true_obj = new CPDF_Boolean(true); |
52 // Number objects. | 53 // Number objects. |
53 CPDF_Number* number_int_obj = new CPDF_Number(1245); | 54 CPDF_Number* number_int_obj = new CPDF_Number(1245); |
54 CPDF_Number* number_float_obj = new CPDF_Number(9.00345f); | 55 CPDF_Number* number_float_obj = new CPDF_Number(9.00345f); |
55 // String objects. | 56 // String objects. |
56 CPDF_String* str_reg_obj = new CPDF_String(L"A simple test"); | 57 CPDF_String* str_reg_obj = new CPDF_String(nullptr, L"A simple test"); |
57 CPDF_String* str_spec_obj = new CPDF_String(L"\t\n"); | 58 CPDF_String* str_spec_obj = new CPDF_String(nullptr, L"\t\n"); |
58 // Name object. | 59 // Name object. |
59 CPDF_Name* name_obj = new CPDF_Name(nullptr, "space"); | 60 CPDF_Name* name_obj = new CPDF_Name(nullptr, "space"); |
60 // Array object. | 61 // Array object. |
61 m_ArrayObj = new CPDF_Array; | 62 m_ArrayObj = new CPDF_Array; |
62 m_ArrayObj->InsertNewAt<CPDF_Number>(0, 8902); | 63 m_ArrayObj->InsertNewAt<CPDF_Number>(0, 8902); |
63 m_ArrayObj->InsertNewAt<CPDF_Name>(1, "address"); | 64 m_ArrayObj->InsertNewAt<CPDF_Name>(1, "address"); |
64 // Dictionary object. | 65 // Dictionary object. |
65 m_DictObj = new CPDF_Dictionary(); | 66 m_DictObj = new CPDF_Dictionary(); |
66 m_DictObj->SetFor("bool", new CPDF_Boolean(false)); | 67 m_DictObj->SetNewFor<CPDF_Boolean>("bool", false); |
67 m_DictObj->SetFor("num", new CPDF_Number(0.23f)); | 68 m_DictObj->SetNewFor<CPDF_Number>("num", 0.23f); |
68 // Stream object. | 69 // Stream object. |
69 const char content[] = "abcdefghijklmnopqrstuvwxyz"; | 70 const char content[] = "abcdefghijklmnopqrstuvwxyz"; |
70 size_t buf_len = FX_ArraySize(content); | 71 size_t buf_len = FX_ArraySize(content); |
71 uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_len)); | 72 uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_len)); |
72 memcpy(buf, content, buf_len); | 73 memcpy(buf, content, buf_len); |
73 m_StreamDictObj = new CPDF_Dictionary(); | 74 m_StreamDictObj = new CPDF_Dictionary(); |
74 m_StreamDictObj->SetFor("key1", new CPDF_String(L" test dict")); | 75 m_StreamDictObj->SetNewFor<CPDF_String>("key1", L" test dict"); |
75 m_StreamDictObj->SetFor("key2", new CPDF_Number(-1)); | 76 m_StreamDictObj->SetNewFor<CPDF_Number>("key2", -1); |
76 CPDF_Stream* stream_obj = new CPDF_Stream(buf, buf_len, m_StreamDictObj); | 77 CPDF_Stream* stream_obj = new CPDF_Stream(buf, buf_len, m_StreamDictObj); |
77 // Null Object. | 78 // Null Object. |
78 CPDF_Null* null_obj = new CPDF_Null; | 79 CPDF_Null* null_obj = new CPDF_Null; |
79 // All direct objects. | 80 // All direct objects. |
80 CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj, | 81 CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj, |
81 number_float_obj, str_reg_obj, str_spec_obj, | 82 number_float_obj, str_reg_obj, str_spec_obj, |
82 name_obj, m_ArrayObj, m_DictObj, | 83 name_obj, m_ArrayObj, m_DictObj, |
83 stream_obj, null_obj}; | 84 stream_obj, null_obj}; |
84 m_DirectObjTypes = { | 85 m_DirectObjTypes = { |
85 CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER, | 86 CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 } | 130 } |
130 return true; | 131 return true; |
131 } | 132 } |
132 case CPDF_Object::DICTIONARY: { | 133 case CPDF_Object::DICTIONARY: { |
133 const CPDF_Dictionary* dict1 = obj1->AsDictionary(); | 134 const CPDF_Dictionary* dict1 = obj1->AsDictionary(); |
134 const CPDF_Dictionary* dict2 = obj2->AsDictionary(); | 135 const CPDF_Dictionary* dict2 = obj2->AsDictionary(); |
135 if (dict1->GetCount() != dict2->GetCount()) | 136 if (dict1->GetCount() != dict2->GetCount()) |
136 return false; | 137 return false; |
137 for (CPDF_Dictionary::const_iterator it = dict1->begin(); | 138 for (CPDF_Dictionary::const_iterator it = dict1->begin(); |
138 it != dict1->end(); ++it) { | 139 it != dict1->end(); ++it) { |
139 if (!Equal(it->second, dict2->GetObjectFor(it->first))) | 140 if (!Equal(it->second.get(), dict2->GetObjectFor(it->first))) |
140 return false; | 141 return false; |
141 } | 142 } |
142 return true; | 143 return true; |
143 } | 144 } |
144 case CPDF_Object::NULLOBJ: | 145 case CPDF_Object::NULLOBJ: |
145 return true; | 146 return true; |
146 case CPDF_Object::STREAM: { | 147 case CPDF_Object::STREAM: { |
147 const CPDF_Stream* stream1 = obj1->AsStream(); | 148 const CPDF_Stream* stream1 = obj1->AsStream(); |
148 const CPDF_Stream* stream2 = obj2->AsStream(); | 149 const CPDF_Stream* stream2 = obj2->AsStream(); |
149 if (!stream1->GetDict() && !stream2->GetDict()) | 150 if (!stream1->GetDict() && !stream2->GetDict()) |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 // Dictionary array. | 549 // Dictionary array. |
549 CPDF_Dictionary* vals[3]; | 550 CPDF_Dictionary* vals[3]; |
550 auto arr = pdfium::MakeUnique<CPDF_Array>(); | 551 auto arr = pdfium::MakeUnique<CPDF_Array>(); |
551 for (size_t i = 0; i < 3; ++i) { | 552 for (size_t i = 0; i < 3; ++i) { |
552 vals[i] = arr->AddNew<CPDF_Dictionary>(); | 553 vals[i] = arr->AddNew<CPDF_Dictionary>(); |
553 for (size_t j = 0; j < 3; ++j) { | 554 for (size_t j = 0; j < 3; ++j) { |
554 std::string key("key"); | 555 std::string key("key"); |
555 char buf[33]; | 556 char buf[33]; |
556 key.append(FXSYS_itoa(j, buf, 10)); | 557 key.append(FXSYS_itoa(j, buf, 10)); |
557 int value = j + 200; | 558 int value = j + 200; |
558 vals[i]->SetFor(key.c_str(), new CPDF_Number(value)); | 559 vals[i]->SetNewFor<CPDF_Number>(key.c_str(), value); |
559 } | 560 } |
560 } | 561 } |
561 for (size_t i = 0; i < 3; ++i) { | 562 for (size_t i = 0; i < 3; ++i) { |
562 TestArrayAccessors(arr.get(), i, // Array and index. | 563 TestArrayAccessors(arr.get(), i, // Array and index. |
563 "", // String value. | 564 "", // String value. |
564 nullptr, // Const string value. | 565 nullptr, // Const string value. |
565 0, // Integer value. | 566 0, // Integer value. |
566 0, // Float value. | 567 0, // Float value. |
567 nullptr, // Array value. | 568 nullptr, // Array value. |
568 vals[i], // Dictionary value. | 569 vals[i], // Dictionary value. |
569 nullptr); // Stream value. | 570 nullptr); // Stream value. |
570 } | 571 } |
571 } | 572 } |
572 { | 573 { |
573 // Stream array. | 574 // Stream array. |
574 CPDF_Dictionary* vals[3]; | 575 CPDF_Dictionary* vals[3]; |
575 CPDF_Stream* stream_vals[3]; | 576 CPDF_Stream* stream_vals[3]; |
576 auto arr = pdfium::MakeUnique<CPDF_Array>(); | 577 auto arr = pdfium::MakeUnique<CPDF_Array>(); |
577 for (size_t i = 0; i < 3; ++i) { | 578 for (size_t i = 0; i < 3; ++i) { |
578 vals[i] = new CPDF_Dictionary(); | 579 vals[i] = new CPDF_Dictionary(); |
579 for (size_t j = 0; j < 3; ++j) { | 580 for (size_t j = 0; j < 3; ++j) { |
580 std::string key("key"); | 581 std::string key("key"); |
581 char buf[33]; | 582 char buf[33]; |
582 key.append(FXSYS_itoa(j, buf, 10)); | 583 key.append(FXSYS_itoa(j, buf, 10)); |
583 int value = j + 200; | 584 int value = j + 200; |
584 vals[i]->SetFor(key.c_str(), new CPDF_Number(value)); | 585 vals[i]->SetNewFor<CPDF_Number>(key.c_str(), value); |
585 } | 586 } |
586 uint8_t content[] = "content: this is a stream"; | 587 uint8_t content[] = "content: this is a stream"; |
587 size_t data_size = FX_ArraySize(content); | 588 size_t data_size = FX_ArraySize(content); |
588 uint8_t* data = reinterpret_cast<uint8_t*>(malloc(data_size)); | 589 uint8_t* data = reinterpret_cast<uint8_t*>(malloc(data_size)); |
589 memcpy(data, content, data_size); | 590 memcpy(data, content, data_size); |
590 stream_vals[i] = arr->AddNew<CPDF_Stream>(data, data_size, vals[i]); | 591 stream_vals[i] = arr->AddNew<CPDF_Stream>(data, data_size, vals[i]); |
591 } | 592 } |
592 for (size_t i = 0; i < 3; ++i) { | 593 for (size_t i = 0; i < 3; ++i) { |
593 TestArrayAccessors(arr.get(), i, // Array and index. | 594 TestArrayAccessors(arr.get(), i, // Array and index. |
594 "", // String value. | 595 "", // String value. |
(...skipping 18 matching lines...) Expand all Loading... |
613 arr->InsertNewAt<CPDF_String>(7, "It is a test!", false); | 614 arr->InsertNewAt<CPDF_String>(7, "It is a test!", false); |
614 arr->InsertNewAt<CPDF_Name>(8, "NAME"); | 615 arr->InsertNewAt<CPDF_Name>(8, "NAME"); |
615 arr->InsertNewAt<CPDF_Name>(9, "test"); | 616 arr->InsertNewAt<CPDF_Name>(9, "test"); |
616 arr->InsertNewAt<CPDF_Null>(10); | 617 arr->InsertNewAt<CPDF_Null>(10); |
617 | 618 |
618 CPDF_Array* arr_val = arr->InsertNewAt<CPDF_Array>(11); | 619 CPDF_Array* arr_val = arr->InsertNewAt<CPDF_Array>(11); |
619 arr_val->AddNew<CPDF_Number>(1); | 620 arr_val->AddNew<CPDF_Number>(1); |
620 arr_val->AddNew<CPDF_Number>(2); | 621 arr_val->AddNew<CPDF_Number>(2); |
621 | 622 |
622 CPDF_Dictionary* dict_val = arr->InsertNewAt<CPDF_Dictionary>(12); | 623 CPDF_Dictionary* dict_val = arr->InsertNewAt<CPDF_Dictionary>(12); |
623 dict_val->SetFor("key1", new CPDF_String(nullptr, "Linda", false)); | 624 dict_val->SetNewFor<CPDF_String>("key1", "Linda", false); |
624 dict_val->SetFor("key2", new CPDF_String(nullptr, "Zoe", false)); | 625 dict_val->SetNewFor<CPDF_String>("key2", "Zoe", false); |
625 | 626 |
626 CPDF_Dictionary* stream_dict = new CPDF_Dictionary(); | 627 CPDF_Dictionary* stream_dict = new CPDF_Dictionary(); |
627 stream_dict->SetFor("key1", new CPDF_String(nullptr, "John", false)); | 628 stream_dict->SetNewFor<CPDF_String>("key1", "John", false); |
628 stream_dict->SetFor("key2", new CPDF_String(nullptr, "King", false)); | 629 stream_dict->SetNewFor<CPDF_String>("key2", "King", false); |
629 uint8_t data[] = "A stream for test"; | 630 uint8_t data[] = "A stream for test"; |
630 // The data buffer will be owned by stream object, so it needs to be | 631 // The data buffer will be owned by stream object, so it needs to be |
631 // dynamically allocated. | 632 // dynamically allocated. |
632 size_t buf_size = sizeof(data); | 633 size_t buf_size = sizeof(data); |
633 uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_size)); | 634 uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_size)); |
634 memcpy(buf, data, buf_size); | 635 memcpy(buf, data, buf_size); |
635 CPDF_Stream* stream_val = | 636 CPDF_Stream* stream_val = |
636 arr->InsertNewAt<CPDF_Stream>(13, buf, buf_size, stream_dict); | 637 arr->InsertNewAt<CPDF_Stream>(13, buf, buf_size, stream_dict); |
637 const char* const expected_str[] = { | 638 const char* const expected_str[] = { |
638 "true", "false", "0", "-1234", "2345", "0.05", "", | 639 "true", "false", "0", "-1234", "2345", "0.05", "", |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 EXPECT_TRUE(pRef->IsReference()); | 772 EXPECT_TRUE(pRef->IsReference()); |
772 EXPECT_TRUE(pNum->IsNumber()); | 773 EXPECT_TRUE(pNum->IsNumber()); |
773 EXPECT_NE(pObj, pRef); | 774 EXPECT_NE(pObj, pRef); |
774 EXPECT_EQ(pObj, pNum); | 775 EXPECT_EQ(pObj, pNum); |
775 EXPECT_EQ(42, array->GetIntegerAt(0)); | 776 EXPECT_EQ(42, array->GetIntegerAt(0)); |
776 } | 777 } |
777 | 778 |
778 TEST(PDFDictionaryTest, CloneDirectObject) { | 779 TEST(PDFDictionaryTest, CloneDirectObject) { |
779 CPDF_IndirectObjectHolder objects_holder; | 780 CPDF_IndirectObjectHolder objects_holder; |
780 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary()); | 781 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary()); |
781 dict->SetReferenceFor("foo", &objects_holder, 1234); | 782 dict->SetNewFor<CPDF_Reference>("foo", &objects_holder, 1234); |
782 ASSERT_EQ(1U, dict->GetCount()); | 783 ASSERT_EQ(1U, dict->GetCount()); |
783 CPDF_Object* obj = dict->GetObjectFor("foo"); | 784 CPDF_Object* obj = dict->GetObjectFor("foo"); |
784 ASSERT_TRUE(obj); | 785 ASSERT_TRUE(obj); |
785 EXPECT_TRUE(obj->IsReference()); | 786 EXPECT_TRUE(obj->IsReference()); |
786 | 787 |
787 std::unique_ptr<CPDF_Object> cloned_dict_object = dict->CloneDirectObject(); | 788 std::unique_ptr<CPDF_Object> cloned_dict_object = dict->CloneDirectObject(); |
788 ASSERT_TRUE(cloned_dict_object); | 789 ASSERT_TRUE(cloned_dict_object); |
789 ASSERT_TRUE(cloned_dict_object->IsDictionary()); | 790 ASSERT_TRUE(cloned_dict_object->IsDictionary()); |
790 | 791 |
791 std::unique_ptr<CPDF_Dictionary> cloned_dict = | 792 std::unique_ptr<CPDF_Dictionary> cloned_dict = |
792 ToDictionary(std::move(cloned_dict_object)); | 793 ToDictionary(std::move(cloned_dict_object)); |
793 ASSERT_EQ(1U, cloned_dict->GetCount()); | 794 ASSERT_EQ(1U, cloned_dict->GetCount()); |
794 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); | 795 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); |
795 EXPECT_FALSE(cloned_obj); | 796 EXPECT_FALSE(cloned_obj); |
796 } | 797 } |
797 | 798 |
798 TEST(PDFObjectTest, CloneCheckLoop) { | 799 TEST(PDFObjectTest, CloneCheckLoop) { |
799 { | 800 { |
800 // Create a dictionary/array pair with a reference loop. | 801 // Create a dictionary/array pair with a reference loop. It takes |
| 802 // some work to do this nowadays, in particular we need the |
| 803 // anti-pattern pdfium::WrapUnique(arr.get()). |
801 auto arr_obj = pdfium::MakeUnique<CPDF_Array>(); | 804 auto arr_obj = pdfium::MakeUnique<CPDF_Array>(); |
802 CPDF_Dictionary* dict_obj = arr_obj->InsertNewAt<CPDF_Dictionary>(0); | 805 CPDF_Dictionary* dict_obj = arr_obj->InsertNewAt<CPDF_Dictionary>(0); |
803 dict_obj->SetFor("arr", arr_obj.get()); | 806 dict_obj->SetFor("arr", pdfium::WrapUnique(arr_obj.get())); |
804 // Clone this object to see whether stack overflow will be triggered. | 807 // Clone this object to see whether stack overflow will be triggered. |
805 std::unique_ptr<CPDF_Array> cloned_array = ToArray(arr_obj->Clone()); | 808 std::unique_ptr<CPDF_Array> cloned_array = ToArray(arr_obj->Clone()); |
806 // Cloned object should be the same as the original. | 809 // Cloned object should be the same as the original. |
807 ASSERT_TRUE(cloned_array); | 810 ASSERT_TRUE(cloned_array); |
808 EXPECT_EQ(1u, cloned_array->GetCount()); | 811 EXPECT_EQ(1u, cloned_array->GetCount()); |
809 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0); | 812 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0); |
810 ASSERT_TRUE(cloned_dict); | 813 ASSERT_TRUE(cloned_dict); |
811 ASSERT_TRUE(cloned_dict->IsDictionary()); | 814 ASSERT_TRUE(cloned_dict->IsDictionary()); |
812 // Recursively referenced object is not cloned. | 815 // Recursively referenced object is not cloned. |
813 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr")); | 816 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr")); |
814 } | 817 } |
815 { | 818 { |
816 // Create a dictionary/stream pair with a reference loop. | 819 // Create a dictionary/stream pair with a reference loop. |
817 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); | 820 auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>(); |
818 std::unique_ptr<CPDF_Stream> stream_obj( | 821 CPDF_Stream* stream_obj = |
819 new CPDF_Stream(nullptr, 0, dict_obj)); | 822 dict_obj->SetNewFor<CPDF_Stream>("stream", nullptr, 0, dict_obj.get()); |
820 dict_obj->SetFor("stream", stream_obj.get()); | |
821 | |
822 // Clone this object to see whether stack overflow will be triggered. | 823 // Clone this object to see whether stack overflow will be triggered. |
823 std::unique_ptr<CPDF_Stream> cloned_stream = ToStream(stream_obj->Clone()); | 824 std::unique_ptr<CPDF_Stream> cloned_stream = ToStream(stream_obj->Clone()); |
824 // Cloned object should be the same as the original. | 825 // Cloned object should be the same as the original. |
825 ASSERT_TRUE(cloned_stream); | 826 ASSERT_TRUE(cloned_stream); |
826 CPDF_Object* cloned_dict = cloned_stream->GetDict(); | 827 CPDF_Object* cloned_dict = cloned_stream->GetDict(); |
827 ASSERT_TRUE(cloned_dict); | 828 ASSERT_TRUE(cloned_dict); |
828 ASSERT_TRUE(cloned_dict->IsDictionary()); | 829 ASSERT_TRUE(cloned_dict->IsDictionary()); |
829 // Recursively referenced object is not cloned. | 830 // Recursively referenced object is not cloned. |
830 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream")); | 831 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream")); |
831 } | 832 } |
832 { | 833 { |
833 CPDF_IndirectObjectHolder objects_holder; | 834 CPDF_IndirectObjectHolder objects_holder; |
834 // Create an object with a reference loop. | 835 // Create an object with a reference loop. |
835 CPDF_Dictionary* dict_obj = objects_holder.NewIndirect<CPDF_Dictionary>(); | 836 CPDF_Dictionary* dict_obj = objects_holder.NewIndirect<CPDF_Dictionary>(); |
836 std::unique_ptr<CPDF_Array> arr_obj = pdfium::MakeUnique<CPDF_Array>(); | 837 std::unique_ptr<CPDF_Array> arr_obj = pdfium::MakeUnique<CPDF_Array>(); |
837 arr_obj->InsertNewAt<CPDF_Reference>(0, &objects_holder, | 838 arr_obj->InsertNewAt<CPDF_Reference>(0, &objects_holder, |
838 dict_obj->GetObjNum()); | 839 dict_obj->GetObjNum()); |
839 CPDF_Object* elem0 = arr_obj->GetObjectAt(0); | 840 CPDF_Object* elem0 = arr_obj->GetObjectAt(0); |
840 dict_obj->SetFor("arr", arr_obj.release()); | 841 dict_obj->SetFor("arr", std::move(arr_obj)); |
841 EXPECT_EQ(1u, dict_obj->GetObjNum()); | 842 EXPECT_EQ(1u, dict_obj->GetObjNum()); |
842 ASSERT_TRUE(elem0); | 843 ASSERT_TRUE(elem0); |
843 ASSERT_TRUE(elem0->IsReference()); | 844 ASSERT_TRUE(elem0->IsReference()); |
844 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum()); | 845 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum()); |
845 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect()); | 846 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect()); |
846 | 847 |
847 // Clone this object to see whether stack overflow will be triggered. | 848 // Clone this object to see whether stack overflow will be triggered. |
848 std::unique_ptr<CPDF_Dictionary> cloned_dict = | 849 std::unique_ptr<CPDF_Dictionary> cloned_dict = |
849 ToDictionary(dict_obj->CloneDirectObject()); | 850 ToDictionary(dict_obj->CloneDirectObject()); |
850 // Cloned object should be the same as the original. | 851 // Cloned object should be the same as the original. |
851 ASSERT_TRUE(cloned_dict); | 852 ASSERT_TRUE(cloned_dict); |
852 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); | 853 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); |
853 ASSERT_TRUE(cloned_arr); | 854 ASSERT_TRUE(cloned_arr); |
854 ASSERT_TRUE(cloned_arr->IsArray()); | 855 ASSERT_TRUE(cloned_arr->IsArray()); |
855 EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); | 856 EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); |
856 // Recursively referenced object is not cloned. | 857 // Recursively referenced object is not cloned. |
857 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); | 858 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); |
858 } | 859 } |
859 } | 860 } |
860 | 861 |
861 TEST(PDFDictionaryTest, ConvertIndirect) { | 862 TEST(PDFDictionaryTest, ConvertIndirect) { |
862 CPDF_IndirectObjectHolder objects_holder; | 863 CPDF_IndirectObjectHolder objects_holder; |
863 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary); | 864 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary); |
864 CPDF_Object* pObj = new CPDF_Number(42); | 865 CPDF_Object* pObj = dict->SetNewFor<CPDF_Number>("clams", 42); |
865 dict->SetFor("clams", pObj); | |
866 dict->ConvertToIndirectObjectFor("clams", &objects_holder); | 866 dict->ConvertToIndirectObjectFor("clams", &objects_holder); |
867 CPDF_Object* pRef = dict->GetObjectFor("clams"); | 867 CPDF_Object* pRef = dict->GetObjectFor("clams"); |
868 CPDF_Object* pNum = dict->GetDirectObjectFor("clams"); | 868 CPDF_Object* pNum = dict->GetDirectObjectFor("clams"); |
869 EXPECT_TRUE(pRef->IsReference()); | 869 EXPECT_TRUE(pRef->IsReference()); |
870 EXPECT_TRUE(pNum->IsNumber()); | 870 EXPECT_TRUE(pNum->IsNumber()); |
871 EXPECT_NE(pObj, pRef); | 871 EXPECT_NE(pObj, pRef); |
872 EXPECT_EQ(pObj, pNum); | 872 EXPECT_EQ(pObj, pNum); |
873 EXPECT_EQ(42, dict->GetIntegerFor("clams")); | 873 EXPECT_EQ(42, dict->GetIntegerFor("clams")); |
874 } | 874 } |
OLD | NEW |