mirror of
https://github.com/qpdf/qpdf.git
synced 2024-06-26 07:12:45 +00:00
Fix QPDFObjectHandle::shallowCopy
It's not really a shallow copy. It just doesn't cross indirect object boundaries. The old implementation had a bug that would cause multiple shallow copies of the same object to share memory, which was not the intention.
This commit is contained in:
parent
84cd53f5af
commit
ddd78c1b7f
|
@ -514,10 +514,11 @@ class QPDFObjectHandle
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF* getOwningQPDF();
|
QPDF* getOwningQPDF();
|
||||||
|
|
||||||
// Create a shallow copy of an object as a direct object. Since
|
// Create a shallow of an object as a direct object, but do not
|
||||||
// this is a shallow copy, for dictionaries and arrays, any keys
|
// traverse across indirect object boundaries. That means that,
|
||||||
// or items that were indirect objects will still be indirect
|
// for dictionaries and arrays, any keys or items that were
|
||||||
// objects that point to the same place.
|
// indirect objects will still be indirect objects that point to
|
||||||
|
// the same place.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle shallowCopy();
|
QPDFObjectHandle shallowCopy();
|
||||||
|
|
||||||
|
@ -880,7 +881,7 @@ class QPDFObjectHandle
|
||||||
void objectWarning(std::string const& warning);
|
void objectWarning(std::string const& warning);
|
||||||
void assertType(char const* type_name, bool istype);
|
void assertType(char const* type_name, bool istype);
|
||||||
void dereference();
|
void dereference();
|
||||||
void makeDirectInternal(std::set<int>& visited);
|
void copyObject(std::set<QPDFObjGen>& visited, bool cross_indirect);
|
||||||
void releaseResolved();
|
void releaseResolved();
|
||||||
static void setObjectDescriptionFromInput(
|
static void setObjectDescriptionFromInput(
|
||||||
QPDFObjectHandle, QPDF*, std::string const&,
|
QPDFObjectHandle, QPDF*, std::string const&,
|
||||||
|
|
|
@ -2025,11 +2025,14 @@ QPDFObjectHandle::shallowCopy()
|
||||||
new_obj = *this;
|
new_obj = *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<QPDFObjGen> visited;
|
||||||
|
new_obj.copyObject(visited, false);
|
||||||
return new_obj;
|
return new_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFObjectHandle::makeDirectInternal(std::set<int>& visited)
|
QPDFObjectHandle::copyObject(std::set<QPDFObjGen>& visited,
|
||||||
|
bool cross_indirect)
|
||||||
{
|
{
|
||||||
assertInitialized();
|
assertInitialized();
|
||||||
|
|
||||||
|
@ -2040,17 +2043,17 @@ QPDFObjectHandle::makeDirectInternal(std::set<int>& visited)
|
||||||
"attempt to make a stream into a direct object");
|
"attempt to make a stream into a direct object");
|
||||||
}
|
}
|
||||||
|
|
||||||
int cur_objid = this->m->objid;
|
QPDFObjGen cur_og(this->m->objid, this->m->generation);
|
||||||
if (cur_objid != 0)
|
if (cur_og.getObj() != 0)
|
||||||
{
|
{
|
||||||
if (visited.count(cur_objid))
|
if (visited.count(cur_og))
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "QPDFObjectHandle makeDirect loop");
|
QTC::TC("qpdf", "QPDFObjectHandle makeDirect loop");
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"loop detected while converting object from "
|
"loop detected while converting object from "
|
||||||
"indirect to direct");
|
"indirect to direct");
|
||||||
}
|
}
|
||||||
visited.insert(cur_objid);
|
visited.insert(cur_og);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isReserved())
|
if (isReserved())
|
||||||
|
@ -2105,7 +2108,10 @@ QPDFObjectHandle::makeDirectInternal(std::set<int>& visited)
|
||||||
for (int i = 0; i < n; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
items.push_back(getArrayItem(i));
|
items.push_back(getArrayItem(i));
|
||||||
items.back().makeDirectInternal(visited);
|
if (cross_indirect || (! items.back().isIndirect()))
|
||||||
|
{
|
||||||
|
items.back().copyObject(visited, cross_indirect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
new_obj = new QPDF_Array(items);
|
new_obj = new QPDF_Array(items);
|
||||||
}
|
}
|
||||||
|
@ -2118,7 +2124,10 @@ QPDFObjectHandle::makeDirectInternal(std::set<int>& visited)
|
||||||
iter != keys.end(); ++iter)
|
iter != keys.end(); ++iter)
|
||||||
{
|
{
|
||||||
items[*iter] = getKey(*iter);
|
items[*iter] = getKey(*iter);
|
||||||
items[*iter].makeDirectInternal(visited);
|
if (cross_indirect || (! items[*iter].isIndirect()))
|
||||||
|
{
|
||||||
|
items[*iter].copyObject(visited, cross_indirect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
new_obj = new QPDF_Dictionary(items);
|
new_obj = new QPDF_Dictionary(items);
|
||||||
}
|
}
|
||||||
|
@ -2130,17 +2139,17 @@ QPDFObjectHandle::makeDirectInternal(std::set<int>& visited)
|
||||||
|
|
||||||
this->m->obj = new_obj;
|
this->m->obj = new_obj;
|
||||||
|
|
||||||
if (cur_objid)
|
if (cur_og.getObj())
|
||||||
{
|
{
|
||||||
visited.erase(cur_objid);
|
visited.erase(cur_og);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFObjectHandle::makeDirect()
|
QPDFObjectHandle::makeDirect()
|
||||||
{
|
{
|
||||||
std::set<int> visited;
|
std::set<QPDFObjGen> visited;
|
||||||
makeDirectInternal(visited);
|
copyObject(visited, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -5,17 +5,22 @@
|
||||||
%% Original object ID: 1 0
|
%% Original object ID: 1 0
|
||||||
1 0 obj
|
1 0 obj
|
||||||
<<
|
<<
|
||||||
/Pages 2 0 R
|
/Pages 3 0 R
|
||||||
/Type /Catalog
|
/Type /Catalog
|
||||||
>>
|
>>
|
||||||
endobj
|
endobj
|
||||||
|
|
||||||
%% Original object ID: 2 0
|
%% Original object ID: 8 0
|
||||||
2 0 obj
|
2 0 obj
|
||||||
|
null
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 2 0
|
||||||
|
3 0 obj
|
||||||
<<
|
<<
|
||||||
/Count 1
|
/Count 1
|
||||||
/Kids [
|
/Kids [
|
||||||
3 0 R
|
4 0 R
|
||||||
]
|
]
|
||||||
/Type /Pages
|
/Type /Pages
|
||||||
>>
|
>>
|
||||||
|
@ -23,21 +28,21 @@ endobj
|
||||||
|
|
||||||
%% Page 1
|
%% Page 1
|
||||||
%% Original object ID: 3 0
|
%% Original object ID: 3 0
|
||||||
3 0 obj
|
4 0 obj
|
||||||
<<
|
<<
|
||||||
/Contents 4 0 R
|
/Contents 5 0 R
|
||||||
/MediaBox [
|
/MediaBox [
|
||||||
0
|
0
|
||||||
0
|
0
|
||||||
612
|
612
|
||||||
792
|
792
|
||||||
]
|
]
|
||||||
/Parent 2 0 R
|
/Parent 3 0 R
|
||||||
/Resources <<
|
/Resources <<
|
||||||
/Font <<
|
/Font <<
|
||||||
/F1 6 0 R
|
/F1 7 0 R
|
||||||
>>
|
>>
|
||||||
/ProcSet 7 0 R
|
/ProcSet 8 0 R
|
||||||
>>
|
>>
|
||||||
/Type /Page
|
/Type /Page
|
||||||
>>
|
>>
|
||||||
|
@ -45,9 +50,9 @@ endobj
|
||||||
|
|
||||||
%% Contents for page 1
|
%% Contents for page 1
|
||||||
%% Original object ID: 4 0
|
%% Original object ID: 4 0
|
||||||
4 0 obj
|
5 0 obj
|
||||||
<<
|
<<
|
||||||
/Length 5 0 R
|
/Length 6 0 R
|
||||||
>>
|
>>
|
||||||
stream
|
stream
|
||||||
BT
|
BT
|
||||||
|
@ -58,12 +63,12 @@ ET
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
|
|
||||||
5 0 obj
|
6 0 obj
|
||||||
44
|
44
|
||||||
endobj
|
endobj
|
||||||
|
|
||||||
%% Original object ID: 6 0
|
%% Original object ID: 6 0
|
||||||
6 0 obj
|
7 0 obj
|
||||||
<<
|
<<
|
||||||
/BaseFont /Helvetica
|
/BaseFont /Helvetica
|
||||||
/Encoding /WinAnsiEncoding
|
/Encoding /WinAnsiEncoding
|
||||||
|
@ -74,7 +79,7 @@ endobj
|
||||||
endobj
|
endobj
|
||||||
|
|
||||||
%% Original object ID: 5 0
|
%% Original object ID: 5 0
|
||||||
7 0 obj
|
8 0 obj
|
||||||
[
|
[
|
||||||
/PDF
|
/PDF
|
||||||
/Text
|
/Text
|
||||||
|
@ -82,29 +87,30 @@ endobj
|
||||||
endobj
|
endobj
|
||||||
|
|
||||||
xref
|
xref
|
||||||
0 8
|
0 9
|
||||||
0000000000 65535 f
|
0000000000 65535 f
|
||||||
0000000052 00000 n
|
0000000052 00000 n
|
||||||
0000000133 00000 n
|
0000000133 00000 n
|
||||||
0000000242 00000 n
|
0000000181 00000 n
|
||||||
0000000484 00000 n
|
0000000290 00000 n
|
||||||
0000000583 00000 n
|
0000000532 00000 n
|
||||||
0000000629 00000 n
|
0000000631 00000 n
|
||||||
0000000774 00000 n
|
0000000677 00000 n
|
||||||
|
0000000822 00000 n
|
||||||
trailer <<
|
trailer <<
|
||||||
/QTest [
|
/QTest [
|
||||||
1
|
1
|
||||||
(2)
|
(2)
|
||||||
null
|
2 0 R
|
||||||
0.0
|
0.0
|
||||||
-0.0
|
-0.0
|
||||||
0.
|
0.
|
||||||
-0.
|
-0.
|
||||||
]
|
]
|
||||||
/Root 1 0 R
|
/Root 1 0 R
|
||||||
/Size 8
|
/Size 9
|
||||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||||
>>
|
>>
|
||||||
startxref
|
startxref
|
||||||
809
|
857
|
||||||
%%EOF
|
%%EOF
|
||||||
|
|
Loading…
Reference in New Issue
Block a user