From 1bb23d0545dfe2d651cb22b6135d99c1c9ef85d5 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 10 Dec 2022 19:48:07 +0000 Subject: Refactor QPDF_Array::insertItem and rename to insert --- libqpdf/QPDFObjectHandle.cc | 9 ++++++--- libqpdf/QPDF_Array.cc | 31 ++++++++++++------------------- libqpdf/SparseOHArray.cc | 22 +++++++++++----------- libqpdf/qpdf/QPDF_Array.hh | 2 +- qpdf/qpdf.testcov | 1 + qpdf/qtest/qpdf/object-types-os.out | 1 + qpdf/qtest/qpdf/object-types.out | 1 + qpdf/test_driver.cc | 1 + 8 files changed, 34 insertions(+), 34 deletions(-) diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 0c4d45ae..fa8b9136 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -932,9 +932,12 @@ QPDFObjectHandle::setArrayFromVector(std::vector const& items) void QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item) { - auto array = asArray(); - if (array) { - array->insertItem(at, item); + if (auto array = asArray()) { + if (!array->insert(at, item)) { + objectWarning( + "ignoring attempt to insert out of bounds array item"); + QTC::TC("qpdf", "QPDFObjectHandle insert array bounds"); + } } else { typeWarning("array", "ignoring attempt to insert item"); QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item"); diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index 5a80cdf5..7633266e 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -236,31 +236,24 @@ QPDF_Array::setFromVector(std::vector>&& v) } } -void -QPDF_Array::insertItem(int at, QPDFObjectHandle const& item) +bool +QPDF_Array::insert(int at, QPDFObjectHandle const& item) { - if (sparse) { + int sz = size(); + if (at < 0 || at > sz) { // As special case, also allow insert beyond the end - if ((at < 0) || (at > sp_elements.size())) { - throw std::logic_error( - "INTERNAL ERROR: bounds error accessing QPDF_Array element"); - } - sp_elements.insert(at, item); + return false; + } else if (at == sz) { + push_back(item); } else { - // As special case, also allow insert beyond the end - size_t idx = QIntC::to_size(at); - if ((at < 0) || (at > QIntC::to_int(elements.size()))) { - throw std::logic_error( - "INTERNAL ERROR: bounds error accessing QPDF_Array element"); - } - if (idx == elements.size()) { - // Allow inserting to the last position - elements.push_back(item.getObj()); + checkOwnership(item); + if (sparse) { + sp_elements.insert(at, item); } else { - int n = int(idx); - elements.insert(elements.cbegin() + n, item.getObj()); + elements.insert(elements.cbegin() + at, item.getObj()); } } + return true; } void diff --git a/libqpdf/SparseOHArray.cc b/libqpdf/SparseOHArray.cc index 48716deb..8f6c02d7 100644 --- a/libqpdf/SparseOHArray.cc +++ b/libqpdf/SparseOHArray.cc @@ -64,23 +64,23 @@ SparseOHArray::erase(int idx) void SparseOHArray::insert(int idx, QPDFObjectHandle oh) { - if (idx > this->n_elements) { - throw std::logic_error("bounds error inserting item to SparseOHArray"); - } else if (idx == this->n_elements) { + if (idx == n_elements) { // Allow inserting to the last position append(oh); } else { - decltype(this->elements) dest; - for (auto const& iter: this->elements) { - if (iter.first < idx) { - dest.insert(iter); + auto iter = elements.crbegin(); + while (iter != elements.crend()) { + auto key = (iter++)->first; + if (key >= idx) { + auto nh = elements.extract(key); + ++nh.key(); + elements.insert(std::move(nh)); } else { - dest[iter.first + 1] = iter.second; + break; } } - this->elements = dest; - this->elements[idx] = oh.getObj(); - ++this->n_elements; + elements[idx] = oh.getObj(); + ++n_elements; } } diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index 61f14d0f..8768c9ad 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -33,7 +33,7 @@ class QPDF_Array: public QPDFValue void setItem(int, QPDFObjectHandle const&); void setFromVector(std::vector const& items); void setFromVector(std::vector>&& items); - void insertItem(int at, QPDFObjectHandle const& item); + bool insert(int at, QPDFObjectHandle const& item); void push_back(QPDFObjectHandle const& item); void eraseItem(int at); diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index cad67565..736c02b4 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -305,6 +305,7 @@ QPDFObjectHandle array treating as empty vector 0 QPDFObjectHandle array ignoring set item 0 QPDFObjectHandle array ignoring replace items 0 QPDFObjectHandle array ignoring insert item 0 +QPDFObjectHandle insert array bounds 0 QPDFObjectHandle array ignoring append item 0 QPDFObjectHandle array ignoring erase item 0 QPDFObjectHandle dictionary false for hasKey 0 diff --git a/qpdf/qtest/qpdf/object-types-os.out b/qpdf/qtest/qpdf/object-types-os.out index a95fa4d8..1ba84d50 100644 --- a/qpdf/qtest/qpdf/object-types-os.out +++ b/qpdf/qtest/qpdf/object-types-os.out @@ -5,6 +5,7 @@ WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operatio WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to append item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to erase out of bounds array item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to erase out of bounds array item +WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 384: ignoring attempt to insert out of bounds array item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to erase item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to insert item WARNING: object-types-os.pdf object stream 1, object 7 0 at offset 429: operation for array attempted on object of type integer: ignoring attempt to replace items diff --git a/qpdf/qtest/qpdf/object-types.out b/qpdf/qtest/qpdf/object-types.out index 718105db..bf41044e 100644 --- a/qpdf/qtest/qpdf/object-types.out +++ b/qpdf/qtest/qpdf/object-types.out @@ -5,6 +5,7 @@ WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempt WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to append item WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to erase out of bounds array item WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to erase out of bounds array item +WARNING: object-types.pdf, object 8 0 at offset 717: ignoring attempt to insert out of bounds array item WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to erase item WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to insert item WARNING: object-types.pdf, object 8 0 at offset 669: operation for array attempted on object of type integer: ignoring attempt to replace items diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 5bae8b54..8c54ad01 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -1506,6 +1506,7 @@ test_42(QPDF& pdf, char const* arg2) integer.appendItem(null); array.eraseItem(-1); array.eraseItem(16059); + array.insertItem(42, "/Dontpanic"_qpdf); integer.eraseItem(0); integer.insertItem(0, null); integer.setArrayFromVector(std::vector()); -- cgit v1.2.3-70-g09d2