mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Security: replace operator[] with at
For std::string and std::vector, replace operator[] with at. This was done using an automated process. See README.hardening for details.
This commit is contained in:
parent
4229457068
commit
ac9c1f0d56
@ -1,5 +1,10 @@
|
||||
2013-10-05 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* Replace operator[] in std::string and std::vector with "at" in
|
||||
order to get bounds checking. This reduces the chances that
|
||||
incorrect code will result in data exposure or buffer overruns.
|
||||
See README.hardening for additional notes.
|
||||
|
||||
* Use cryptographically secure random number generation when
|
||||
available. See additional notes in README.
|
||||
|
||||
|
93
README.hardening
Normal file
93
README.hardening
Normal file
@ -0,0 +1,93 @@
|
||||
Avoiding operator[]
|
||||
===================
|
||||
|
||||
During a security review by Red Hat security team (specifically
|
||||
Florian Weimer), it was discovered that qpdf used std::string and
|
||||
std::vector's operator[], which has no bounds checking by design.
|
||||
Instead, using those objects' at() method is preferable since it does
|
||||
bounds checking. Florian has a tool that can detect all uses of these
|
||||
methods and report them. I have a short perl script that
|
||||
automatically corrects any such uses. The perl script is not intended
|
||||
to be general, but it could be reasonably general. The only known
|
||||
shortcut is that it might not work very well with some cases of nested
|
||||
[]'s like a[b[c]] or with cases where there are line breaks inside the
|
||||
brackets. For qpdf's coding style, it worked on all cases reported.
|
||||
|
||||
To use this, obtain htcondor-analyzer, run it, and respond to the
|
||||
report. Here's what I did.
|
||||
|
||||
sudo aptitude install libclang-dev llvm llvm-dev clang
|
||||
cd /tmp
|
||||
git clone https://github.com/fweimer/htcondor-analyzer
|
||||
# HEAD = 5fa06fc68a9b0677e9de162279185d58ba1e8477 at this writing
|
||||
cd htcondor-analyzer
|
||||
make
|
||||
|
||||
in qpdf
|
||||
|
||||
./autogen.sh
|
||||
/tmp/htcondor-analyzer/create-db
|
||||
CC=/tmp/htcondor-analyzer/cc CXX=/tmp/htcondor-analyzer/cxx ./configure --disable-shared --disable-werror
|
||||
# to remove conftest.c
|
||||
\rm htcondor-analyzer.sqlite
|
||||
/tmp/htcondor-analyzer/create-db
|
||||
|
||||
Repeat until no more errors:
|
||||
|
||||
/tmp/fix-at.pl is shown below.
|
||||
|
||||
make
|
||||
/tmp/htcondor-analyzer/report | grep std:: | grep qpdf >| /tmp/r
|
||||
perl /tmp/fix-at.pl /tmp/r
|
||||
# move all *.new over the original file. patmv is my script. Can
|
||||
# also use a for loop.
|
||||
patmv -f s/.new// **/*.new
|
||||
|
||||
---------- /tmp/fix-at.pl ----------
|
||||
#!/usr/bin/env perl
|
||||
require 5.008;
|
||||
use warnings;
|
||||
use strict;
|
||||
use File::Basename;
|
||||
|
||||
my $whoami = basename($0);
|
||||
|
||||
my %to_fix = ();
|
||||
while (<>)
|
||||
{
|
||||
chomp;
|
||||
die unless m/^([^:]+):(\d+):(\d+):\s*(.*)$/;
|
||||
my ($file, $line, $col, $message) = ($1, $2, $3, $4);
|
||||
if ($message !~ m/operator\[\]/)
|
||||
{
|
||||
warn "skipping $_\n";
|
||||
next;
|
||||
}
|
||||
push(@{$to_fix{$file}}, [$line, $col, $message]);
|
||||
}
|
||||
foreach my $file (sort keys %to_fix)
|
||||
{
|
||||
open(F, "<$file") or die;
|
||||
my @lines = (<F>);
|
||||
close(F);
|
||||
my $last = "";
|
||||
my @data = reverse sort { ($a->[0] <=> $b->[0]) || ($a->[1] <=> $b->[1]) } @{$to_fix{$file}};
|
||||
foreach my $d (@data)
|
||||
{
|
||||
my ($line, $col) = @$d;
|
||||
next if $last eq "$line:$col";
|
||||
$last = "$line:$col";
|
||||
die if $line-- < 1;
|
||||
die if $col-- < 1;
|
||||
print $lines[$line];
|
||||
$lines[$line] =~ s/^(.{$col})([^\[]+)\[([^\]]+)\]/$1$2.at($3)/ or die "$file:$last\n";
|
||||
print $lines[$line];
|
||||
}
|
||||
open(F, ">$file.new") or die;
|
||||
foreach my $line (@lines)
|
||||
{
|
||||
print F $line;
|
||||
}
|
||||
close(F) or die;
|
||||
}
|
||||
--------------------
|
@ -43,6 +43,9 @@ Release Reminders
|
||||
casting policy in the manual, and ensure that integer types are
|
||||
properly handled.
|
||||
|
||||
* Remember to avoid using operator[] with std::string or
|
||||
std::vector. See README.hardening for details.
|
||||
|
||||
* Increment shared library version information as needed
|
||||
(libqpdf/build.mk)
|
||||
|
||||
|
@ -31,7 +31,7 @@ void print_lines(std::vector<int>& numbers)
|
||||
{
|
||||
for (unsigned int i = 0; i < numbers.size() - 1; ++i)
|
||||
{
|
||||
if (numbers[i])
|
||||
if (numbers.at(i))
|
||||
{
|
||||
std::cout << "| ";
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info -key");
|
||||
cur_key = argv[i];
|
||||
if (! ((cur_key.length() > 0) && (cur_key[0] == '/')))
|
||||
if (! ((cur_key.length() > 0) && (cur_key.at(0) == '/')))
|
||||
{
|
||||
cur_key = "/" + cur_key;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ int main(int argc, char* argv[])
|
||||
usage();
|
||||
}
|
||||
|
||||
QPDFObjectHandle page = pages[pageno-1];
|
||||
QPDFObjectHandle page = pages.at(pageno-1);
|
||||
QPDFObjectHandle contents = page.getKey("/Contents");
|
||||
ParserCallbacks cb;
|
||||
QPDFObjectHandle::parseContentStream(contents, &cb);
|
||||
|
@ -109,7 +109,7 @@ Pl_LZWDecoder::getFirstChar(int code)
|
||||
throw std::logic_error(
|
||||
"Pl_LZWDecoder::getFirstChar: table overflow");
|
||||
}
|
||||
Buffer& b = table[idx];
|
||||
Buffer& b = table.at(idx);
|
||||
result = b.getBuffer()[0];
|
||||
}
|
||||
else
|
||||
@ -142,7 +142,7 @@ Pl_LZWDecoder::addToTable(unsigned char next)
|
||||
throw std::logic_error(
|
||||
"Pl_LZWDecoder::addToTable: table overflow");
|
||||
}
|
||||
Buffer& b = table[idx];
|
||||
Buffer& b = table.at(idx);
|
||||
last_data = b.getBuffer();
|
||||
last_size = b.getSize();
|
||||
}
|
||||
@ -238,7 +238,7 @@ Pl_LZWDecoder::handleCode(int code)
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer& b = table[code - 258];
|
||||
Buffer& b = table.at(code - 258);
|
||||
getNext()->write(b.getBuffer(), b.getSize());
|
||||
}
|
||||
}
|
||||
|
@ -531,7 +531,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
|
||||
// For xref_table, these will always be small enough to be ints
|
||||
qpdf_offset_t f1 = QUtil::string_to_ll(m2.getMatch(1).c_str());
|
||||
int f2 = atoi(m2.getMatch(2).c_str());
|
||||
char type = m2.getMatch(3)[0];
|
||||
char type = m2.getMatch(3).at(0);
|
||||
if (type == 'f')
|
||||
{
|
||||
// Save deleted items until after we've checked the
|
||||
@ -758,17 +758,17 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
|
||||
long long num_entries = 0;
|
||||
for (unsigned int i = 1; i < indx.size(); i += 2)
|
||||
{
|
||||
if (indx[i] > max_num_entries - num_entries)
|
||||
if (indx.at(i) > max_num_entries - num_entries)
|
||||
{
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
|
||||
"xref stream", xref_offset,
|
||||
"Cross-reference stream claims to contain"
|
||||
" too many entries: " +
|
||||
QUtil::int_to_string(indx[i]) + " " +
|
||||
QUtil::int_to_string(indx.at(i)) + " " +
|
||||
QUtil::int_to_string(max_num_entries) + " " +
|
||||
QUtil::int_to_string(num_entries));
|
||||
}
|
||||
num_entries += indx[i];
|
||||
num_entries += indx.at(i);
|
||||
}
|
||||
|
||||
// entry_size and num_entries have both been validated to ensure
|
||||
@ -829,9 +829,9 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
|
||||
// based on /Index. The generation number is 0 unless this is
|
||||
// an uncompressed object record, in which case the generation
|
||||
// number appears as the third field.
|
||||
int obj = indx[cur_chunk] + chunk_count;
|
||||
int obj = indx.at(cur_chunk) + chunk_count;
|
||||
++chunk_count;
|
||||
if (chunk_count >= indx[cur_chunk + 1])
|
||||
if (chunk_count >= indx.at(cur_chunk + 1))
|
||||
{
|
||||
cur_chunk += 2;
|
||||
chunk_count = 0;
|
||||
|
@ -712,7 +712,7 @@ QPDFObjectHandle::parse(std::string const& object_str,
|
||||
size_t offset = input->tell();
|
||||
while (offset < object_str.length())
|
||||
{
|
||||
if (! isspace(object_str[offset]))
|
||||
if (! isspace(object_str.at(offset)))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle trailing data in parse");
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, input->getName(),
|
||||
@ -966,8 +966,8 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
std::string const& value = token.getValue();
|
||||
if ((value == "R") && (in_array || in_dictionary) &&
|
||||
(olist.size() >= 2) &&
|
||||
(olist[olist.size() - 1].isInteger()) &&
|
||||
(olist[olist.size() - 2].isInteger()))
|
||||
(olist.at(olist.size() - 1).isInteger()) &&
|
||||
(olist.at(olist.size() - 2).isInteger()))
|
||||
{
|
||||
if (context == 0)
|
||||
{
|
||||
@ -979,8 +979,8 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
// Try to resolve indirect objects
|
||||
object = newIndirect(
|
||||
context,
|
||||
olist[olist.size() - 2].getIntValue(),
|
||||
olist[olist.size() - 1].getIntValue());
|
||||
olist.at(olist.size() - 2).getIntValue(),
|
||||
olist.at(olist.size() - 1).getIntValue());
|
||||
olist.pop_back();
|
||||
olist.pop_back();
|
||||
}
|
||||
@ -1067,8 +1067,8 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
}
|
||||
for (unsigned int i = 0; i < olist.size(); i += 2)
|
||||
{
|
||||
QPDFObjectHandle key_obj = olist[i];
|
||||
QPDFObjectHandle val = olist[i + 1];
|
||||
QPDFObjectHandle key_obj = olist.at(i);
|
||||
QPDFObjectHandle val = olist.at(i + 1);
|
||||
if (! key_obj.isName())
|
||||
{
|
||||
throw QPDFExc(
|
||||
|
@ -61,7 +61,7 @@ QPDFTokenizer::resolveLiteral()
|
||||
{
|
||||
PCRE num_re("^[\\+\\-]?(?:\\.\\d+|\\d+(?:\\.\\d+)?)$");
|
||||
|
||||
if ((val.length() > 0) && (val[0] == '/'))
|
||||
if ((val.length() > 0) && (val.at(0) == '/'))
|
||||
{
|
||||
type = tt_name;
|
||||
// Deal with # in name token. Note: '/' by itself is a
|
||||
@ -397,8 +397,8 @@ QPDFTokenizer::presentCharacter(char ch)
|
||||
std::string nval;
|
||||
for (unsigned int i = 0; i < val.length(); i += 2)
|
||||
{
|
||||
num[0] = val[i];
|
||||
num[1] = val[i+1];
|
||||
num[0] = val.at(i);
|
||||
num[1] = val.at(i+1);
|
||||
char nch = static_cast<char>(strtol(num, 0, 16));
|
||||
nval += nch;
|
||||
}
|
||||
|
@ -1569,7 +1569,7 @@ QPDFWriter::writeObjectStreamOffsets(std::vector<qpdf_offset_t>& offsets,
|
||||
}
|
||||
writeString(QUtil::int_to_string(i + first_obj));
|
||||
writeString(" ");
|
||||
writeString(QUtil::int_to_string(offsets[i]));
|
||||
writeString(QUtil::int_to_string(offsets.at(i)));
|
||||
}
|
||||
writeString("\n");
|
||||
}
|
||||
@ -1603,7 +1603,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object)
|
||||
{
|
||||
// Adjust offsets to skip over comment before first object
|
||||
|
||||
first = offsets[0];
|
||||
first = offsets.at(0);
|
||||
for (std::vector<qpdf_offset_t>::iterator iter = offsets.begin();
|
||||
iter != offsets.end(); ++iter)
|
||||
{
|
||||
@ -2745,7 +2745,7 @@ QPDFWriter::writeLinearized()
|
||||
if (pass == 2)
|
||||
{
|
||||
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
|
||||
int first_page_object = obj_renumber[pages[0].getObjGen()];
|
||||
int first_page_object = obj_renumber[pages.at(0).getObjGen()];
|
||||
int npages = pages.size();
|
||||
|
||||
writeString(" /Linearized 1 /L ");
|
||||
|
@ -60,7 +60,7 @@ QPDF_Array::getItem(int n) const
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: bounds error accessing QPDF_Array element");
|
||||
}
|
||||
return this->items[n];
|
||||
return this->items.at(n);
|
||||
}
|
||||
|
||||
std::vector<QPDFObjectHandle> const&
|
||||
@ -74,7 +74,7 @@ QPDF_Array::setItem(int n, QPDFObjectHandle const& oh)
|
||||
{
|
||||
// Call getItem for bounds checking
|
||||
(void) getItem(n);
|
||||
this->items[n] = oh;
|
||||
this->items.at(n) = oh;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -21,10 +21,10 @@ QPDF_Name::normalizeName(std::string const& name)
|
||||
return name;
|
||||
}
|
||||
std::string result;
|
||||
result += name[0];
|
||||
result += name.at(0);
|
||||
for (unsigned int i = 1; i < name.length(); ++i)
|
||||
{
|
||||
char ch = name[i];
|
||||
char ch = name.at(i);
|
||||
// Don't use locale/ctype here; follow PDF spec guidelines.
|
||||
if (strchr("#()<>[]{}/%", ch) || (ch < 33) || (ch > 126))
|
||||
{
|
||||
|
@ -310,7 +310,7 @@ QPDF_Stream::filterable(std::vector<std::string>& filters,
|
||||
|
||||
for (unsigned int i = 0; i < filters.size(); ++i)
|
||||
{
|
||||
QPDFObjectHandle decode_item = decode_parms[i];
|
||||
QPDFObjectHandle decode_item = decode_parms.at(i);
|
||||
if (decode_item.isNull())
|
||||
{
|
||||
// okay
|
||||
@ -318,7 +318,7 @@ QPDF_Stream::filterable(std::vector<std::string>& filters,
|
||||
else if (decode_item.isDictionary())
|
||||
{
|
||||
if (! understandDecodeParams(
|
||||
filters[i], decode_item,
|
||||
filters.at(i), decode_item,
|
||||
predictor, columns, early_code_change))
|
||||
{
|
||||
filterable = false;
|
||||
|
@ -55,7 +55,7 @@ QPDF_String::unparse(bool force_binary)
|
||||
int consecutive_printable = 0;
|
||||
for (unsigned int i = 0; i < this->val.length(); ++i)
|
||||
{
|
||||
char ch = this->val[i];
|
||||
char ch = this->val.at(i);
|
||||
// Note: do not use locale to determine printability. The
|
||||
// PDF specification accepts arbitrary binary data. Some
|
||||
// locales imply multibyte characters. We'll consider
|
||||
@ -97,7 +97,7 @@ QPDF_String::unparse(bool force_binary)
|
||||
result += "(";
|
||||
for (unsigned int i = 0; i < this->val.length(); ++i)
|
||||
{
|
||||
char ch = this->val[i];
|
||||
char ch = this->val.at(i);
|
||||
switch (ch)
|
||||
{
|
||||
case '\n':
|
||||
@ -135,7 +135,7 @@ QPDF_String::unparse(bool force_binary)
|
||||
default:
|
||||
if (is_iso_latin1_printable(ch))
|
||||
{
|
||||
result += this->val[i];
|
||||
result += this->val.at(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -164,7 +164,7 @@ QPDF_String::getUTF8Val() const
|
||||
std::string result;
|
||||
size_t len = this->val.length();
|
||||
if ((len >= 2) && (len % 2 == 0) &&
|
||||
(this->val[0] == '\xfe') && (this->val[1] == '\xff'))
|
||||
(this->val.at(0) == '\xfe') && (this->val.at(1) == '\xff'))
|
||||
{
|
||||
// This is a Unicode string using big-endian UTF-16. This
|
||||
// code uses unsigned long and unsigned short to hold
|
||||
@ -181,8 +181,8 @@ QPDF_String::getUTF8Val() const
|
||||
// discarded, and a low codepoint not preceded by a high
|
||||
// codepoint will just get its low 10 bits output.
|
||||
unsigned short bits =
|
||||
(static_cast<unsigned char>(this->val[i]) << 8) +
|
||||
static_cast<unsigned char>(this->val[i+1]);
|
||||
(static_cast<unsigned char>(this->val.at(i)) << 8) +
|
||||
static_cast<unsigned char>(this->val.at(i+1));
|
||||
if ((bits & 0xFC00) == 0xD800)
|
||||
{
|
||||
codepoint = 0x10000 + ((bits & 0x3FF) << 10);
|
||||
@ -209,7 +209,7 @@ QPDF_String::getUTF8Val() const
|
||||
{
|
||||
for (unsigned int i = 0; i < len; ++i)
|
||||
{
|
||||
result += QUtil::toUTF8(static_cast<unsigned char>(this->val[i]));
|
||||
result += QUtil::toUTF8(static_cast<unsigned char>(this->val.at(i)));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -312,7 +312,7 @@ hash_V5(std::string const& password,
|
||||
int E_mod_3 = 0;
|
||||
for (unsigned int i = 0; i < 16; ++i)
|
||||
{
|
||||
E_mod_3 += static_cast<unsigned char>(E[i]);
|
||||
E_mod_3 += static_cast<unsigned char>(E.at(i));
|
||||
}
|
||||
E_mod_3 %= 3;
|
||||
int next_hash = ((E_mod_3 == 0) ? 256 :
|
||||
|
@ -33,7 +33,7 @@ load_vector_int(BitStream& bit_stream, int nitems, std::vector<T>& vec,
|
||||
{
|
||||
vec.push_back(T());
|
||||
}
|
||||
vec[i].*field = bit_stream.getBits(bits_wanted);
|
||||
vec.at(i).*field = bit_stream.getBits(bits_wanted);
|
||||
}
|
||||
if (static_cast<int>(vec.size()) != nitems)
|
||||
{
|
||||
@ -54,9 +54,9 @@ load_vector_vector(BitStream& bit_stream,
|
||||
// into the vec2 vector field of the ith item of vec1.
|
||||
for (int i1 = 0; i1 < nitems1; ++i1)
|
||||
{
|
||||
for (int i2 = 0; i2 < vec1[i1].*nitems2; ++i2)
|
||||
for (int i2 = 0; i2 < vec1.at(i1).*nitems2; ++i2)
|
||||
{
|
||||
(vec1[i1].*vec2).push_back(bit_stream.getBits(bits_wanted));
|
||||
(vec1.at(i1).*vec2).push_back(bit_stream.getBits(bits_wanted));
|
||||
}
|
||||
}
|
||||
bit_stream.skipToNextByte();
|
||||
@ -237,8 +237,8 @@ QPDF::readLinearizationData()
|
||||
}
|
||||
|
||||
// H: hint table offset/length for primary and overflow hint tables
|
||||
int H0_offset = H_items[0];
|
||||
int H0_length = H_items[1];
|
||||
int H0_offset = H_items.at(0);
|
||||
int H0_length = H_items.at(1);
|
||||
int H1_offset = 0;
|
||||
int H1_length = 0;
|
||||
if (H_items.size() == 4)
|
||||
@ -246,8 +246,8 @@ QPDF::readLinearizationData()
|
||||
// Acrobat doesn't read or write these (as PDF 1.4), so we
|
||||
// don't have a way to generate a test case.
|
||||
// QTC::TC("qpdf", "QPDF overflow hint table");
|
||||
H1_offset = H_items[2];
|
||||
H1_length = H_items[3];
|
||||
H1_offset = H_items.at(2);
|
||||
H1_length = H_items.at(3);
|
||||
}
|
||||
|
||||
// P: first page number
|
||||
@ -470,7 +470,7 @@ QPDF::readHSharedObject(BitStream h)
|
||||
1, &HSharedObjectEntry::signature_present);
|
||||
for (int i = 0; i < nitems; ++i)
|
||||
{
|
||||
if (entries[i].signature_present)
|
||||
if (entries.at(i).signature_present)
|
||||
{
|
||||
// Skip 128-bit MD5 hash. These are not supported by
|
||||
// acrobat, so they should probably never be there. We
|
||||
@ -512,7 +512,7 @@ QPDF::checkLinearizationInternal()
|
||||
|
||||
// O: object number of first page
|
||||
std::vector<QPDFObjectHandle> const& pages = getAllPages();
|
||||
if (p.first_page_object != pages[0].getObjectID())
|
||||
if (p.first_page_object != pages.at(0).getObjectID())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF err /O mismatch");
|
||||
errors.push_back("first page object (/O) mismatch");
|
||||
@ -528,7 +528,7 @@ QPDF::checkLinearizationInternal()
|
||||
|
||||
for (int i = 0; i < npages; ++i)
|
||||
{
|
||||
QPDFObjectHandle const& page = pages[i];
|
||||
QPDFObjectHandle const& page = pages.at(i);
|
||||
QPDFObjGen og(page.getObjGen());
|
||||
if (this->xref_table[og].getType() == 2)
|
||||
{
|
||||
@ -776,7 +776,7 @@ QPDF::checkHPageOffset(std::list<std::string>& errors,
|
||||
unsigned int npages = pages.size();
|
||||
int table_offset = adjusted_offset(
|
||||
this->page_offset_hints.first_page_offset);
|
||||
QPDFObjGen first_page_og(pages[0].getObjGen());
|
||||
QPDFObjGen first_page_og(pages.at(0).getObjGen());
|
||||
assert(this->xref_table.count(first_page_og) > 0);
|
||||
int offset = getLinearizationOffset(first_page_og);
|
||||
if (table_offset != offset)
|
||||
@ -786,13 +786,13 @@ QPDF::checkHPageOffset(std::list<std::string>& errors,
|
||||
|
||||
for (unsigned int pageno = 0; pageno < npages; ++pageno)
|
||||
{
|
||||
QPDFObjGen page_og(pages[pageno].getObjGen());
|
||||
QPDFObjGen page_og(pages.at(pageno).getObjGen());
|
||||
int first_object = page_og.getObj();
|
||||
assert(this->xref_table.count(page_og) > 0);
|
||||
offset = getLinearizationOffset(page_og);
|
||||
|
||||
HPageOffsetEntry& he = this->page_offset_hints.entries[pageno];
|
||||
CHPageOffsetEntry& ce = this->c_page_offset_data.entries[pageno];
|
||||
HPageOffsetEntry& he = this->page_offset_hints.entries.at(pageno);
|
||||
CHPageOffsetEntry& ce = this->c_page_offset_data.entries.at(pageno);
|
||||
int h_nobjects = he.delta_nobjects +
|
||||
this->page_offset_hints.min_nobjects;
|
||||
if (h_nobjects != ce.nobjects)
|
||||
@ -837,7 +837,7 @@ QPDF::checkHPageOffset(std::list<std::string>& errors,
|
||||
|
||||
for (int i = 0; i < he.nshared_objects; ++i)
|
||||
{
|
||||
int idx = he.shared_identifiers[i];
|
||||
int idx = he.shared_identifiers.at(i);
|
||||
if (shared_idx_to_obj.count(idx) == 0)
|
||||
{
|
||||
throw std::logic_error(
|
||||
@ -849,13 +849,13 @@ QPDF::checkHPageOffset(std::list<std::string>& errors,
|
||||
|
||||
for (int i = 0; i < ce.nshared_objects; ++i)
|
||||
{
|
||||
int idx = ce.shared_identifiers[i];
|
||||
int idx = ce.shared_identifiers.at(i);
|
||||
if (idx >= this->c_shared_object_data.nshared_total)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"index out of bounds for shared object hint table");
|
||||
}
|
||||
int obj = this->c_shared_object_data.entries[idx].object;
|
||||
int obj = this->c_shared_object_data.entries.at(idx).object;
|
||||
computed_shared.insert(obj);
|
||||
}
|
||||
|
||||
@ -923,7 +923,7 @@ QPDF::checkHSharedObject(std::list<std::string>& errors,
|
||||
// The first nshared_first_page objects are consecutive
|
||||
// objects starting with the first page object. The rest are
|
||||
// consecutive starting from the first_shared_obj object.
|
||||
int cur_object = pages[0].getObjectID();
|
||||
int cur_object = pages.at(0).getObjectID();
|
||||
for (int i = 0; i < so.nshared_total; ++i)
|
||||
{
|
||||
if (i == so.nshared_first_page)
|
||||
@ -937,7 +937,7 @@ QPDF::checkHSharedObject(std::list<std::string>& errors,
|
||||
}
|
||||
else
|
||||
{
|
||||
int obj = this->part8[0].getObjectID();
|
||||
int obj = this->part8.at(0).getObjectID();
|
||||
if (obj != so.first_shared_obj)
|
||||
{
|
||||
errors.push_back(
|
||||
@ -965,7 +965,7 @@ QPDF::checkHSharedObject(std::list<std::string>& errors,
|
||||
}
|
||||
|
||||
idx_to_obj[i] = cur_object;
|
||||
HSharedObjectEntry& se = so.entries[i];
|
||||
HSharedObjectEntry& se = so.entries.at(i);
|
||||
int nobjects = se.nobjects_minus_one + 1;
|
||||
int length = lengthNextN(cur_object, nobjects, errors);
|
||||
int h_length = so.min_group_length + se.delta_group_length;
|
||||
@ -1146,7 +1146,7 @@ QPDF::dumpHPageOffset()
|
||||
|
||||
for (int i1 = 0; i1 < this->linp.npages; ++i1)
|
||||
{
|
||||
HPageOffsetEntry& pe = t.entries[i1];
|
||||
HPageOffsetEntry& pe = t.entries.at(i1);
|
||||
*out_stream
|
||||
<< "Page " << i1 << ":" << std::endl
|
||||
<< " nobjects: " << pe.delta_nobjects + t.min_nobjects
|
||||
@ -1162,9 +1162,9 @@ QPDF::dumpHPageOffset()
|
||||
for (int i2 = 0; i2 < pe.nshared_objects; ++i2)
|
||||
{
|
||||
*out_stream << " identifier " << i2 << ": "
|
||||
<< pe.shared_identifiers[i2] << std::endl;
|
||||
<< pe.shared_identifiers.at(i2) << std::endl;
|
||||
*out_stream << " numerator " << i2 << ": "
|
||||
<< pe.shared_numerators[i2] << std::endl;
|
||||
<< pe.shared_numerators.at(i2) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1191,7 +1191,7 @@ QPDF::dumpHSharedObject()
|
||||
|
||||
for (int i = 0; i < t.nshared_total; ++i)
|
||||
{
|
||||
HSharedObjectEntry& se = t.entries[i];
|
||||
HSharedObjectEntry& se = t.entries.at(i);
|
||||
*out_stream << "Shared Object " << i << ":" << std::endl;
|
||||
*out_stream << " group length: "
|
||||
<< se.delta_group_length + t.min_group_length << std::endl;
|
||||
@ -1522,7 +1522,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
||||
// will do the same.
|
||||
|
||||
// First, place the actual first page object itself.
|
||||
QPDFObjGen first_page_og(pages[0].getObjGen());
|
||||
QPDFObjGen first_page_og(pages.at(0).getObjGen());
|
||||
if (! lc_first_page_private.count(first_page_og))
|
||||
{
|
||||
throw std::logic_error(
|
||||
@ -1530,8 +1530,8 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
||||
"object not in lc_first_page_private");
|
||||
}
|
||||
lc_first_page_private.erase(first_page_og);
|
||||
this->c_linp.first_page_object = pages[0].getObjectID();
|
||||
this->part6.push_back(pages[0]);
|
||||
this->c_linp.first_page_object = pages.at(0).getObjectID();
|
||||
this->part6.push_back(pages.at(0));
|
||||
|
||||
// The PDF spec "recommends" an order for the rest of the objects,
|
||||
// but we are going to disregard it except to the extent that it
|
||||
@ -1562,7 +1562,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
||||
// in garbage values for all the shared object identifiers on the
|
||||
// first page.
|
||||
|
||||
this->c_page_offset_data.entries[0].nobjects = this->part6.size();
|
||||
this->c_page_offset_data.entries.at(0).nobjects = this->part6.size();
|
||||
|
||||
// Part 7: other pages' private objects
|
||||
|
||||
@ -1571,7 +1571,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
||||
{
|
||||
// Place this page's page object
|
||||
|
||||
QPDFObjGen page_og(pages[i].getObjGen());
|
||||
QPDFObjGen page_og(pages.at(i).getObjGen());
|
||||
if (! lc_other_page_private.count(page_og))
|
||||
{
|
||||
throw std::logic_error(
|
||||
@ -1580,12 +1580,12 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
||||
QUtil::int_to_string(i) + " not in lc_other_page_private");
|
||||
}
|
||||
lc_other_page_private.erase(page_og);
|
||||
this->part7.push_back(pages[i]);
|
||||
this->part7.push_back(pages.at(i));
|
||||
|
||||
// Place all non-shared objects referenced by this page,
|
||||
// updating the page object count for the hint table.
|
||||
|
||||
this->c_page_offset_data.entries[i].nobjects = 1;
|
||||
this->c_page_offset_data.entries.at(i).nobjects = 1;
|
||||
|
||||
ObjUser ou(ObjUser::ou_page, i);
|
||||
assert(this->obj_user_to_objects.count(ou) > 0);
|
||||
@ -1598,7 +1598,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
||||
{
|
||||
lc_other_page_private.erase(og);
|
||||
this->part7.push_back(objGenToIndirect(og));
|
||||
++this->c_page_offset_data.entries[i].nobjects;
|
||||
++this->c_page_offset_data.entries.at(i).nobjects;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1649,7 +1649,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
||||
// thumbnail hint tables.
|
||||
for (unsigned int i = 0; i < npages; ++i)
|
||||
{
|
||||
QPDFObjectHandle thumb = pages[i].getKey("/Thumb");
|
||||
QPDFObjectHandle thumb = pages.at(i).getKey("/Thumb");
|
||||
thumb = getUncompressedObject(thumb, object_stream_data);
|
||||
if (! thumb.isNull())
|
||||
{
|
||||
@ -1758,7 +1758,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
||||
if (! this->part8.empty())
|
||||
{
|
||||
this->c_shared_object_data.first_shared_obj =
|
||||
this->part8[0].getObjectID();
|
||||
this->part8.at(0).getObjectID();
|
||||
for (std::vector<QPDFObjectHandle>::iterator iter =
|
||||
this->part8.begin();
|
||||
iter != this->part8.end(); ++iter)
|
||||
@ -1781,7 +1781,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
||||
|
||||
for (unsigned int i = 1; i < npages; ++i)
|
||||
{
|
||||
CHPageOffsetEntry& pe = this->c_page_offset_data.entries[i];
|
||||
CHPageOffsetEntry& pe = this->c_page_offset_data.entries.at(i);
|
||||
ObjUser ou(ObjUser::ou_page, i);
|
||||
assert(this->obj_user_to_objects.count(ou) > 0);
|
||||
std::set<QPDFObjGen> const& ogs = this->obj_user_to_objects[ou];
|
||||
@ -1892,12 +1892,12 @@ QPDF::calculateHPageOffset(
|
||||
// Calculate minimum and maximum values for number of objects per
|
||||
// page and page length.
|
||||
|
||||
int min_nobjects = cphe[0].nobjects;
|
||||
int min_nobjects = cphe.at(0).nobjects;
|
||||
int max_nobjects = min_nobjects;
|
||||
int min_length = outputLengthNextN(
|
||||
pages[0].getObjectID(), min_nobjects, lengths, obj_renumber);
|
||||
pages.at(0).getObjectID(), min_nobjects, lengths, obj_renumber);
|
||||
int max_length = min_length;
|
||||
int max_shared = cphe[0].nshared_objects;
|
||||
int max_shared = cphe.at(0).nshared_objects;
|
||||
|
||||
HPageOffset& ph = this->page_offset_hints;
|
||||
std::vector<HPageOffsetEntry>& phe = ph.entries;
|
||||
@ -1912,10 +1912,10 @@ QPDF::calculateHPageOffset(
|
||||
// Repeat calculations for page 0 so we can assign to phe[i]
|
||||
// without duplicating those assignments.
|
||||
|
||||
int nobjects = cphe[i].nobjects;
|
||||
int nobjects = cphe.at(i).nobjects;
|
||||
int length = outputLengthNextN(
|
||||
pages[i].getObjectID(), nobjects, lengths, obj_renumber);
|
||||
int nshared = cphe[i].nshared_objects;
|
||||
pages.at(i).getObjectID(), nobjects, lengths, obj_renumber);
|
||||
int nshared = cphe.at(i).nshared_objects;
|
||||
|
||||
min_nobjects = std::min(min_nobjects, nobjects);
|
||||
max_nobjects = std::max(max_nobjects, nobjects);
|
||||
@ -1923,13 +1923,13 @@ QPDF::calculateHPageOffset(
|
||||
max_length = std::max(max_length, length);
|
||||
max_shared = std::max(max_shared, nshared);
|
||||
|
||||
phe[i].delta_nobjects = nobjects;
|
||||
phe[i].delta_page_length = length;
|
||||
phe[i].nshared_objects = nshared;
|
||||
phe.at(i).delta_nobjects = nobjects;
|
||||
phe.at(i).delta_page_length = length;
|
||||
phe.at(i).nshared_objects = nshared;
|
||||
}
|
||||
|
||||
ph.min_nobjects = min_nobjects;
|
||||
int in_page0_id = pages[0].getObjectID();
|
||||
int in_page0_id = pages.at(0).getObjectID();
|
||||
int out_page0_id = (*(obj_renumber.find(in_page0_id))).second;
|
||||
ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset();
|
||||
ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects);
|
||||
@ -1951,17 +1951,17 @@ QPDF::calculateHPageOffset(
|
||||
for (unsigned int i = 0; i < npages; ++i)
|
||||
{
|
||||
// Adjust delta entries
|
||||
assert(phe[i].delta_nobjects >= min_nobjects);
|
||||
assert(phe[i].delta_page_length >= min_length);
|
||||
phe[i].delta_nobjects -= min_nobjects;
|
||||
phe[i].delta_page_length -= min_length;
|
||||
phe[i].delta_content_length = phe[i].delta_page_length;
|
||||
assert(phe.at(i).delta_nobjects >= min_nobjects);
|
||||
assert(phe.at(i).delta_page_length >= min_length);
|
||||
phe.at(i).delta_nobjects -= min_nobjects;
|
||||
phe.at(i).delta_page_length -= min_length;
|
||||
phe.at(i).delta_content_length = phe.at(i).delta_page_length;
|
||||
|
||||
for (int j = 0; j < cphe[i].nshared_objects; ++j)
|
||||
for (int j = 0; j < cphe.at(i).nshared_objects; ++j)
|
||||
{
|
||||
phe[i].shared_identifiers.push_back(
|
||||
cphe[i].shared_identifiers[j]);
|
||||
phe[i].shared_numerators.push_back(0);
|
||||
phe.at(i).shared_identifiers.push_back(
|
||||
cphe.at(i).shared_identifiers.at(j));
|
||||
phe.at(i).shared_numerators.push_back(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1979,18 +1979,18 @@ QPDF::calculateHSharedObject(
|
||||
soe.clear();
|
||||
|
||||
int min_length = outputLengthNextN(
|
||||
csoe[0].object, 1, lengths, obj_renumber);
|
||||
csoe.at(0).object, 1, lengths, obj_renumber);
|
||||
int max_length = min_length;
|
||||
|
||||
for (int i = 0; i < cso.nshared_total; ++i)
|
||||
{
|
||||
// Assign absolute numbers to deltas; adjust later
|
||||
int length = outputLengthNextN(
|
||||
csoe[i].object, 1, lengths, obj_renumber);
|
||||
csoe.at(i).object, 1, lengths, obj_renumber);
|
||||
min_length = std::min(min_length, length);
|
||||
max_length = std::max(max_length, length);
|
||||
soe.push_back(HSharedObjectEntry());
|
||||
soe[i].delta_group_length = length;
|
||||
soe.at(i).delta_group_length = length;
|
||||
}
|
||||
if (soe.size() != static_cast<size_t>(cso.nshared_total))
|
||||
{
|
||||
@ -2012,8 +2012,8 @@ QPDF::calculateHSharedObject(
|
||||
for (int i = 0; i < cso.nshared_total; ++i)
|
||||
{
|
||||
// Adjust deltas
|
||||
assert(soe[i].delta_group_length >= min_length);
|
||||
soe[i].delta_group_length -= min_length;
|
||||
assert(soe.at(i).delta_group_length >= min_length);
|
||||
soe.at(i).delta_group_length -= min_length;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2051,7 +2051,7 @@ write_vector_int(BitWriter& w, int nitems, std::vector<T>& vec,
|
||||
|
||||
for (int i = 0; i < nitems; ++i)
|
||||
{
|
||||
w.writeBits(vec[i].*field, bits);
|
||||
w.writeBits(vec.at(i).*field, bits);
|
||||
}
|
||||
// The PDF spec says that each hint table starts at a byte
|
||||
// boundary. Each "row" actually must start on a byte boundary.
|
||||
@ -2068,9 +2068,9 @@ write_vector_vector(BitWriter& w,
|
||||
// from the vec2 vector field of the ith item of vec1.
|
||||
for (int i1 = 0; i1 < nitems1; ++i1)
|
||||
{
|
||||
for (int i2 = 0; i2 < vec1[i1].*nitems2; ++i2)
|
||||
for (int i2 = 0; i2 < vec1.at(i1).*nitems2; ++i2)
|
||||
{
|
||||
w.writeBits((vec1[i1].*vec2)[i2], bits);
|
||||
w.writeBits((vec1.at(i1).*vec2).at(i2), bits);
|
||||
}
|
||||
}
|
||||
w.flush();
|
||||
@ -2151,7 +2151,7 @@ QPDF::writeHSharedObject(BitWriter& w)
|
||||
for (int i = 0; i < nitems; ++i)
|
||||
{
|
||||
// If signature were present, we'd have to write a 128-bit hash.
|
||||
assert(entries[i].signature_present == 0);
|
||||
assert(entries.at(i).signature_present == 0);
|
||||
}
|
||||
write_vector_int(w, nitems, entries,
|
||||
t.nbits_nobjects,
|
||||
|
@ -91,7 +91,7 @@ QPDF::optimize(std::map<int, int> const& object_stream_data,
|
||||
for (int pageno = 0; pageno < n; ++pageno)
|
||||
{
|
||||
updateObjectMaps(ObjUser(ObjUser::ou_page, pageno),
|
||||
this->all_pages[pageno]);
|
||||
this->all_pages.at(pageno));
|
||||
}
|
||||
|
||||
// Traverse document-level items
|
||||
|
@ -114,8 +114,8 @@ QPDF::flattenPagesTree()
|
||||
for (int pos = 0; pos < len; ++pos)
|
||||
{
|
||||
// populate pageobj_to_pages_pos and fix parent pointer
|
||||
insertPageobjToPage(this->all_pages[pos], pos, true);
|
||||
this->all_pages[pos].replaceKey("/Parent", pages);
|
||||
insertPageobjToPage(this->all_pages.at(pos), pos, true);
|
||||
this->all_pages.at(pos).replaceKey("/Parent", pages);
|
||||
}
|
||||
|
||||
pages.replaceKey("/Kids", QPDFObjectHandle::newArray(this->all_pages));
|
||||
@ -194,7 +194,7 @@ QPDF::insertPage(QPDFObjectHandle newpage, int pos)
|
||||
assert(this->all_pages.size() == static_cast<size_t>(npages));
|
||||
for (int i = pos + 1; i < npages; ++i)
|
||||
{
|
||||
insertPageobjToPage(this->all_pages[i], i, false);
|
||||
insertPageobjToPage(this->all_pages.at(i), i, false);
|
||||
}
|
||||
insertPageobjToPage(newpage, pos, true);
|
||||
assert(this->pageobj_to_pages_pos.size() == static_cast<size_t>(npages));
|
||||
@ -221,7 +221,7 @@ QPDF::removePage(QPDFObjectHandle page)
|
||||
assert(this->pageobj_to_pages_pos.size() == static_cast<size_t>(npages));
|
||||
for (int i = pos; i < npages; ++i)
|
||||
{
|
||||
insertPageobjToPage(this->all_pages[i], i, false);
|
||||
insertPageobjToPage(this->all_pages.at(i), i, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ QUtil::hex_encode(std::string const& input)
|
||||
for (unsigned int i = 0; i < input.length(); ++i)
|
||||
{
|
||||
result += QUtil::int_to_string_base(
|
||||
static_cast<int>(static_cast<unsigned char>(input[i])), 16, 2);
|
||||
static_cast<int>(static_cast<unsigned char>(input.at(i))), 16, 2);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
10
qpdf/qpdf.cc
10
qpdf/qpdf.cc
@ -441,7 +441,7 @@ static std::vector<int> parse_numrange(char const* range, int max,
|
||||
p = 0;
|
||||
for (size_t i = 0; i < work.size(); i += 2)
|
||||
{
|
||||
int num = work[i];
|
||||
int num = work.at(i);
|
||||
// max == 0 means we don't know the max and are just
|
||||
// testing for valid syntax.
|
||||
if ((max > 0) && ((num < 1) || (num > max)))
|
||||
@ -451,11 +451,11 @@ static std::vector<int> parse_numrange(char const* range, int max,
|
||||
}
|
||||
if (i == 0)
|
||||
{
|
||||
result.push_back(work[i]);
|
||||
result.push_back(work.at(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
int separator = work[i-1];
|
||||
int separator = work.at(i-1);
|
||||
if (separator == comma)
|
||||
{
|
||||
result.push_back(num);
|
||||
@ -1664,7 +1664,7 @@ int main(int argc, char* argv[])
|
||||
// Pages are specified from 1 but numbered
|
||||
// from 0 in the vector
|
||||
int pageno = *pageno_iter - 1;
|
||||
pdf.addPage(page_data.orig_pages[pageno], false);
|
||||
pdf.addPage(page_data.orig_pages.at(pageno), false);
|
||||
if (page_data.qpdf == &pdf)
|
||||
{
|
||||
// This is a page from the original file.
|
||||
@ -1683,7 +1683,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
if (selected_from_orig.count(pageno) == 0)
|
||||
{
|
||||
pdf.replaceObject(orig_pages[pageno].getObjGen(),
|
||||
pdf.replaceObject(orig_pages.at(pageno).getObjGen(),
|
||||
QPDFObjectHandle::newNull());
|
||||
}
|
||||
}
|
||||
|
@ -603,10 +603,10 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
else if (n == 10)
|
||||
{
|
||||
std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
|
||||
pages[0].addPageContents(
|
||||
pages.at(0).addPageContents(
|
||||
QPDFObjectHandle::newStream(
|
||||
&pdf, "BT /F1 12 Tf 72 620 Td (Baked) Tj ET\n"), true);
|
||||
pages[0].addPageContents(
|
||||
pages.at(0).addPageContents(
|
||||
QPDFObjectHandle::newStream(
|
||||
&pdf, "BT /F1 18 Tf 72 520 Td (Mashed) Tj ET\n"), false);
|
||||
|
||||
@ -659,7 +659,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
" not called 4-page file");
|
||||
}
|
||||
// Swap pages 2 and 3
|
||||
pdf.swapObjects(pages[1].getObjGen(), pages[2].getObjGen());
|
||||
pdf.swapObjects(pages.at(1).getObjGen(), pages.at(2).getObjGen());
|
||||
// Replace object and swap objects
|
||||
QPDFObjectHandle trailer = pdf.getTrailer();
|
||||
QPDFObjectHandle qdict = trailer.getKey("/QDict");
|
||||
@ -700,7 +700,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
std::map<std::string, QPDFObjectHandle> dict_items =
|
||||
qarray.getDictAsMap();
|
||||
if ((array_elements.size() == 1) &&
|
||||
(array_elements[0].getName() == "/Array") &&
|
||||
(array_elements.at(0).getName() == "/Array") &&
|
||||
(dict_items.size() == 1) &&
|
||||
(dict_items["/NewDict"].getIntValue() == 2))
|
||||
{
|
||||
@ -738,12 +738,12 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
assert(pages.size() == 9);
|
||||
pdf.removePage(*pages.begin()); // original page 0
|
||||
assert(pages.size() == 8);
|
||||
checkPageContents(pages[4], "Original page 5");
|
||||
pdf.removePage(pages[4]); // original page 5
|
||||
checkPageContents(pages.at(4), "Original page 5");
|
||||
pdf.removePage(pages.at(4)); // original page 5
|
||||
assert(pages.size() == 7);
|
||||
checkPageContents(pages[4], "Original page 6");
|
||||
checkPageContents(pages[0], "Original page 1");
|
||||
checkPageContents(pages[6], "Original page 8");
|
||||
checkPageContents(pages.at(4), "Original page 6");
|
||||
checkPageContents(pages.at(0), "Original page 1");
|
||||
checkPageContents(pages.at(6), "Original page 8");
|
||||
|
||||
// Insert pages
|
||||
|
||||
@ -760,7 +760,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
// dictionary and modify it. Using the results of
|
||||
// getDictAsMap to create a new dictionary effectively creates
|
||||
// a shallow copy.
|
||||
QPDFObjectHandle page_template = pages[0];
|
||||
QPDFObjectHandle page_template = pages.at(0);
|
||||
std::vector<QPDFObjectHandle> new_pages;
|
||||
for (std::vector<QPDFObjectHandle>::iterator iter = contents.begin();
|
||||
iter != contents.end(); ++iter)
|
||||
@ -781,25 +781,25 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
}
|
||||
|
||||
// Now insert the pages
|
||||
pdf.addPage(new_pages[0], true);
|
||||
checkPageContents(pages[0], "New page 1");
|
||||
pdf.addPageAt(new_pages[1], true, pages[0]);
|
||||
assert(pages[0].getObjGen() == new_pages[1].getObjGen());
|
||||
pdf.addPageAt(new_pages[2], true, pages[5]);
|
||||
assert(pages[5].getObjGen() == new_pages[2].getObjGen());
|
||||
pdf.addPageAt(new_pages[3], false, pages[5]);
|
||||
assert(pages[6].getObjGen() == new_pages[3].getObjGen());
|
||||
pdf.addPage(new_pages.at(0), true);
|
||||
checkPageContents(pages.at(0), "New page 1");
|
||||
pdf.addPageAt(new_pages.at(1), true, pages.at(0));
|
||||
assert(pages.at(0).getObjGen() == new_pages.at(1).getObjGen());
|
||||
pdf.addPageAt(new_pages.at(2), true, pages.at(5));
|
||||
assert(pages.at(5).getObjGen() == new_pages.at(2).getObjGen());
|
||||
pdf.addPageAt(new_pages.at(3), false, pages.at(5));
|
||||
assert(pages.at(6).getObjGen() == new_pages.at(3).getObjGen());
|
||||
assert(pages.size() == 11);
|
||||
pdf.addPage(new_pages[4], false);
|
||||
assert(pages[11].getObjGen() == new_pages[4].getObjGen());
|
||||
pdf.addPageAt(new_pages[5], false, pages.back());
|
||||
pdf.addPage(new_pages.at(4), false);
|
||||
assert(pages.at(11).getObjGen() == new_pages.at(4).getObjGen());
|
||||
pdf.addPageAt(new_pages.at(5), false, pages.back());
|
||||
assert(pages.size() == 13);
|
||||
checkPageContents(pages[0], "New page 0");
|
||||
checkPageContents(pages[1], "New page 1");
|
||||
checkPageContents(pages[5], "New page 5");
|
||||
checkPageContents(pages[6], "New page 6");
|
||||
checkPageContents(pages[11], "New page 11");
|
||||
checkPageContents(pages[12], "New page 12");
|
||||
checkPageContents(pages.at(0), "New page 0");
|
||||
checkPageContents(pages.at(1), "New page 1");
|
||||
checkPageContents(pages.at(5), "New page 5");
|
||||
checkPageContents(pages.at(6), "New page 6");
|
||||
checkPageContents(pages.at(11), "New page 11");
|
||||
checkPageContents(pages.at(12), "New page 12");
|
||||
|
||||
// Exercise writing to FILE*
|
||||
FILE* out = QUtil::safe_fopen("a.pdf", "wb");
|
||||
@ -816,7 +816,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
QPDFObjectHandle contents = createPageContents(pdf, "New page 10");
|
||||
QPDFObjectHandle page =
|
||||
pdf.makeIndirectObject(
|
||||
QPDFObjectHandle(all_pages[0]).shallowCopy());
|
||||
QPDFObjectHandle(all_pages.at(0)).shallowCopy());
|
||||
page.replaceKey("/Contents", contents);
|
||||
|
||||
// Insert the page manually.
|
||||
@ -843,7 +843,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
// The input file to this test case is broken to exercise an
|
||||
// error condition.
|
||||
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
|
||||
pdf.removePage(pages[0]);
|
||||
pdf.removePage(pages.at(0));
|
||||
std::cout << "you can't see this" << std::endl;
|
||||
}
|
||||
else if (n == 18)
|
||||
@ -854,7 +854,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
// Remove pages from various places, checking to make sure
|
||||
// that our pages reference is getting updated.
|
||||
assert(pages.size() == 10);
|
||||
QPDFObjectHandle page5 = pages[5];
|
||||
QPDFObjectHandle page5 = pages.at(5);
|
||||
pdf.removePage(page5);
|
||||
pdf.addPage(page5, false);
|
||||
assert(pages.size() == 10);
|
||||
@ -871,7 +871,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
|
||||
|
||||
// Try to insert a page that's already there.
|
||||
pdf.addPage(pages[5], false);
|
||||
pdf.addPage(pages.at(5), false);
|
||||
std::cout << "you can't see this" << std::endl;
|
||||
}
|
||||
else if (n == 20)
|
||||
@ -893,7 +893,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
{
|
||||
// Try to shallow copy a stream
|
||||
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
|
||||
QPDFObjectHandle page = pages[0];
|
||||
QPDFObjectHandle page = pages.at(0);
|
||||
QPDFObjectHandle contents = page.getKey("/Contents");
|
||||
contents.shallowCopy();
|
||||
std::cout << "you can't see this" << std::endl;
|
||||
@ -902,7 +902,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
{
|
||||
// Try to remove a page we don't have
|
||||
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
|
||||
QPDFObjectHandle page = pages[0];
|
||||
QPDFObjectHandle page = pages.at(0);
|
||||
pdf.removePage(page);
|
||||
pdf.removePage(page);
|
||||
std::cout << "you can't see this" << std::endl;
|
||||
@ -1109,9 +1109,9 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
QPDF final;
|
||||
final.processFile("b.pdf", "user");
|
||||
std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
|
||||
std::string orig_contents = getPageContents(pages[0]);
|
||||
std::string orig_contents = getPageContents(pages.at(0));
|
||||
pages = final.getAllPages();
|
||||
std::string new_contents = getPageContents(pages[0]);
|
||||
std::string new_contents = getPageContents(pages.at(0));
|
||||
if (orig_contents != new_contents)
|
||||
{
|
||||
std::cout << "oops -- page contents don't match" << std::endl
|
||||
@ -1226,7 +1226,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
bool is_binary = false;
|
||||
for (size_t i = 0; i < data.size(); ++i)
|
||||
{
|
||||
if ((data[i] < 0) || (data[i] > 126))
|
||||
if ((data.at(i) < 0) || (data.at(i) > 126))
|
||||
{
|
||||
is_binary = true;
|
||||
break;
|
||||
@ -1239,9 +1239,9 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
i < std::min(data.size(), static_cast<size_t>(20));
|
||||
++i)
|
||||
{
|
||||
if ((data[i] >= 32) && (data[i] <= 126))
|
||||
if ((data.at(i) >= 32) && (data.at(i) <= 126))
|
||||
{
|
||||
t += data[i];
|
||||
t += data.at(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -286,8 +286,8 @@ static void check_pdf(char const* filename)
|
||||
{
|
||||
int pageno = i + 1;
|
||||
std::cout << "page " << pageno << " of " << npages << std::endl;
|
||||
check_page_contents(pageno, pages[i]);
|
||||
check_image(pageno, pages[i]);
|
||||
check_page_contents(pageno, pages.at(i));
|
||||
check_image(pageno, pages.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user