2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-05-31 01:10:51 +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:
Jay Berkenbilt 2013-10-05 19:42:39 -04:00
parent 4229457068
commit ac9c1f0d56
23 changed files with 254 additions and 153 deletions

View File

@ -1,5 +1,10 @@
2013-10-05 Jay Berkenbilt <ejb@ql.org> 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 * Use cryptographically secure random number generation when
available. See additional notes in README. available. See additional notes in README.

93
README.hardening Normal file
View 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;
}
--------------------

View File

@ -43,6 +43,9 @@ Release Reminders
casting policy in the manual, and ensure that integer types are casting policy in the manual, and ensure that integer types are
properly handled. 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 * Increment shared library version information as needed
(libqpdf/build.mk) (libqpdf/build.mk)

View File

@ -31,7 +31,7 @@ void print_lines(std::vector<int>& numbers)
{ {
for (unsigned int i = 0; i < numbers.size() - 1; ++i) for (unsigned int i = 0; i < numbers.size() - 1; ++i)
{ {
if (numbers[i]) if (numbers.at(i))
{ {
std::cout << "| "; std::cout << "| ";
} }

View File

@ -128,7 +128,7 @@ int main(int argc, char* argv[])
{ {
QTC::TC("examples", "pdf-mod-info -key"); QTC::TC("examples", "pdf-mod-info -key");
cur_key = argv[i]; 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; cur_key = "/" + cur_key;
} }

View File

@ -74,7 +74,7 @@ int main(int argc, char* argv[])
usage(); usage();
} }
QPDFObjectHandle page = pages[pageno-1]; QPDFObjectHandle page = pages.at(pageno-1);
QPDFObjectHandle contents = page.getKey("/Contents"); QPDFObjectHandle contents = page.getKey("/Contents");
ParserCallbacks cb; ParserCallbacks cb;
QPDFObjectHandle::parseContentStream(contents, &cb); QPDFObjectHandle::parseContentStream(contents, &cb);

View File

@ -109,7 +109,7 @@ Pl_LZWDecoder::getFirstChar(int code)
throw std::logic_error( throw std::logic_error(
"Pl_LZWDecoder::getFirstChar: table overflow"); "Pl_LZWDecoder::getFirstChar: table overflow");
} }
Buffer& b = table[idx]; Buffer& b = table.at(idx);
result = b.getBuffer()[0]; result = b.getBuffer()[0];
} }
else else
@ -142,7 +142,7 @@ Pl_LZWDecoder::addToTable(unsigned char next)
throw std::logic_error( throw std::logic_error(
"Pl_LZWDecoder::addToTable: table overflow"); "Pl_LZWDecoder::addToTable: table overflow");
} }
Buffer& b = table[idx]; Buffer& b = table.at(idx);
last_data = b.getBuffer(); last_data = b.getBuffer();
last_size = b.getSize(); last_size = b.getSize();
} }
@ -238,7 +238,7 @@ Pl_LZWDecoder::handleCode(int code)
} }
else else
{ {
Buffer& b = table[code - 258]; Buffer& b = table.at(code - 258);
getNext()->write(b.getBuffer(), b.getSize()); getNext()->write(b.getBuffer(), b.getSize());
} }
} }

View File

@ -531,7 +531,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
// For xref_table, these will always be small enough to be ints // 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()); qpdf_offset_t f1 = QUtil::string_to_ll(m2.getMatch(1).c_str());
int f2 = atoi(m2.getMatch(2).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') if (type == 'f')
{ {
// Save deleted items until after we've checked the // 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; long long num_entries = 0;
for (unsigned int i = 1; i < indx.size(); i += 2) 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(), throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
"xref stream", xref_offset, "xref stream", xref_offset,
"Cross-reference stream claims to contain" "Cross-reference stream claims to contain"
" too many entries: " + " 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(max_num_entries) + " " +
QUtil::int_to_string(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 // 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 // based on /Index. The generation number is 0 unless this is
// an uncompressed object record, in which case the generation // an uncompressed object record, in which case the generation
// number appears as the third field. // number appears as the third field.
int obj = indx[cur_chunk] + chunk_count; int obj = indx.at(cur_chunk) + chunk_count;
++chunk_count; ++chunk_count;
if (chunk_count >= indx[cur_chunk + 1]) if (chunk_count >= indx.at(cur_chunk + 1))
{ {
cur_chunk += 2; cur_chunk += 2;
chunk_count = 0; chunk_count = 0;

View File

@ -712,7 +712,7 @@ QPDFObjectHandle::parse(std::string const& object_str,
size_t offset = input->tell(); size_t offset = input->tell();
while (offset < object_str.length()) while (offset < object_str.length())
{ {
if (! isspace(object_str[offset])) if (! isspace(object_str.at(offset)))
{ {
QTC::TC("qpdf", "QPDFObjectHandle trailing data in parse"); QTC::TC("qpdf", "QPDFObjectHandle trailing data in parse");
throw QPDFExc(qpdf_e_damaged_pdf, input->getName(), throw QPDFExc(qpdf_e_damaged_pdf, input->getName(),
@ -966,8 +966,8 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
std::string const& value = token.getValue(); std::string const& value = token.getValue();
if ((value == "R") && (in_array || in_dictionary) && if ((value == "R") && (in_array || in_dictionary) &&
(olist.size() >= 2) && (olist.size() >= 2) &&
(olist[olist.size() - 1].isInteger()) && (olist.at(olist.size() - 1).isInteger()) &&
(olist[olist.size() - 2].isInteger())) (olist.at(olist.size() - 2).isInteger()))
{ {
if (context == 0) if (context == 0)
{ {
@ -979,8 +979,8 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
// Try to resolve indirect objects // Try to resolve indirect objects
object = newIndirect( object = newIndirect(
context, context,
olist[olist.size() - 2].getIntValue(), olist.at(olist.size() - 2).getIntValue(),
olist[olist.size() - 1].getIntValue()); olist.at(olist.size() - 1).getIntValue());
olist.pop_back(); olist.pop_back();
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) for (unsigned int i = 0; i < olist.size(); i += 2)
{ {
QPDFObjectHandle key_obj = olist[i]; QPDFObjectHandle key_obj = olist.at(i);
QPDFObjectHandle val = olist[i + 1]; QPDFObjectHandle val = olist.at(i + 1);
if (! key_obj.isName()) if (! key_obj.isName())
{ {
throw QPDFExc( throw QPDFExc(

View File

@ -61,7 +61,7 @@ QPDFTokenizer::resolveLiteral()
{ {
PCRE num_re("^[\\+\\-]?(?:\\.\\d+|\\d+(?:\\.\\d+)?)$"); PCRE num_re("^[\\+\\-]?(?:\\.\\d+|\\d+(?:\\.\\d+)?)$");
if ((val.length() > 0) && (val[0] == '/')) if ((val.length() > 0) && (val.at(0) == '/'))
{ {
type = tt_name; type = tt_name;
// Deal with # in name token. Note: '/' by itself is a // Deal with # in name token. Note: '/' by itself is a
@ -397,8 +397,8 @@ QPDFTokenizer::presentCharacter(char ch)
std::string nval; std::string nval;
for (unsigned int i = 0; i < val.length(); i += 2) for (unsigned int i = 0; i < val.length(); i += 2)
{ {
num[0] = val[i]; num[0] = val.at(i);
num[1] = val[i+1]; num[1] = val.at(i+1);
char nch = static_cast<char>(strtol(num, 0, 16)); char nch = static_cast<char>(strtol(num, 0, 16));
nval += nch; nval += nch;
} }

View File

@ -1569,7 +1569,7 @@ QPDFWriter::writeObjectStreamOffsets(std::vector<qpdf_offset_t>& offsets,
} }
writeString(QUtil::int_to_string(i + first_obj)); writeString(QUtil::int_to_string(i + first_obj));
writeString(" "); writeString(" ");
writeString(QUtil::int_to_string(offsets[i])); writeString(QUtil::int_to_string(offsets.at(i)));
} }
writeString("\n"); writeString("\n");
} }
@ -1603,7 +1603,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object)
{ {
// Adjust offsets to skip over comment before first 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(); for (std::vector<qpdf_offset_t>::iterator iter = offsets.begin();
iter != offsets.end(); ++iter) iter != offsets.end(); ++iter)
{ {
@ -2745,7 +2745,7 @@ QPDFWriter::writeLinearized()
if (pass == 2) if (pass == 2)
{ {
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages(); 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(); int npages = pages.size();
writeString(" /Linearized 1 /L "); writeString(" /Linearized 1 /L ");

View File

@ -60,7 +60,7 @@ QPDF_Array::getItem(int n) const
throw std::logic_error( throw std::logic_error(
"INTERNAL ERROR: bounds error accessing QPDF_Array element"); "INTERNAL ERROR: bounds error accessing QPDF_Array element");
} }
return this->items[n]; return this->items.at(n);
} }
std::vector<QPDFObjectHandle> const& std::vector<QPDFObjectHandle> const&
@ -74,7 +74,7 @@ QPDF_Array::setItem(int n, QPDFObjectHandle const& oh)
{ {
// Call getItem for bounds checking // Call getItem for bounds checking
(void) getItem(n); (void) getItem(n);
this->items[n] = oh; this->items.at(n) = oh;
} }
void void

View File

@ -21,10 +21,10 @@ QPDF_Name::normalizeName(std::string const& name)
return name; return name;
} }
std::string result; std::string result;
result += name[0]; result += name.at(0);
for (unsigned int i = 1; i < name.length(); ++i) 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. // Don't use locale/ctype here; follow PDF spec guidelines.
if (strchr("#()<>[]{}/%", ch) || (ch < 33) || (ch > 126)) if (strchr("#()<>[]{}/%", ch) || (ch < 33) || (ch > 126))
{ {

View File

@ -310,7 +310,7 @@ QPDF_Stream::filterable(std::vector<std::string>& filters,
for (unsigned int i = 0; i < filters.size(); ++i) 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()) if (decode_item.isNull())
{ {
// okay // okay
@ -318,7 +318,7 @@ QPDF_Stream::filterable(std::vector<std::string>& filters,
else if (decode_item.isDictionary()) else if (decode_item.isDictionary())
{ {
if (! understandDecodeParams( if (! understandDecodeParams(
filters[i], decode_item, filters.at(i), decode_item,
predictor, columns, early_code_change)) predictor, columns, early_code_change))
{ {
filterable = false; filterable = false;

View File

@ -55,7 +55,7 @@ QPDF_String::unparse(bool force_binary)
int consecutive_printable = 0; int consecutive_printable = 0;
for (unsigned int i = 0; i < this->val.length(); ++i) 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 // Note: do not use locale to determine printability. The
// PDF specification accepts arbitrary binary data. Some // PDF specification accepts arbitrary binary data. Some
// locales imply multibyte characters. We'll consider // locales imply multibyte characters. We'll consider
@ -97,7 +97,7 @@ QPDF_String::unparse(bool force_binary)
result += "("; result += "(";
for (unsigned int i = 0; i < this->val.length(); ++i) for (unsigned int i = 0; i < this->val.length(); ++i)
{ {
char ch = this->val[i]; char ch = this->val.at(i);
switch (ch) switch (ch)
{ {
case '\n': case '\n':
@ -135,7 +135,7 @@ QPDF_String::unparse(bool force_binary)
default: default:
if (is_iso_latin1_printable(ch)) if (is_iso_latin1_printable(ch))
{ {
result += this->val[i]; result += this->val.at(i);
} }
else else
{ {
@ -164,7 +164,7 @@ QPDF_String::getUTF8Val() const
std::string result; std::string result;
size_t len = this->val.length(); size_t len = this->val.length();
if ((len >= 2) && (len % 2 == 0) && 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 // This is a Unicode string using big-endian UTF-16. This
// code uses unsigned long and unsigned short to hold // 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 // discarded, and a low codepoint not preceded by a high
// codepoint will just get its low 10 bits output. // codepoint will just get its low 10 bits output.
unsigned short bits = unsigned short bits =
(static_cast<unsigned char>(this->val[i]) << 8) + (static_cast<unsigned char>(this->val.at(i)) << 8) +
static_cast<unsigned char>(this->val[i+1]); static_cast<unsigned char>(this->val.at(i+1));
if ((bits & 0xFC00) == 0xD800) if ((bits & 0xFC00) == 0xD800)
{ {
codepoint = 0x10000 + ((bits & 0x3FF) << 10); codepoint = 0x10000 + ((bits & 0x3FF) << 10);
@ -209,7 +209,7 @@ QPDF_String::getUTF8Val() const
{ {
for (unsigned int i = 0; i < len; ++i) 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; return result;

View File

@ -312,7 +312,7 @@ hash_V5(std::string const& password,
int E_mod_3 = 0; int E_mod_3 = 0;
for (unsigned int i = 0; i < 16; ++i) 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; E_mod_3 %= 3;
int next_hash = ((E_mod_3 == 0) ? 256 : int next_hash = ((E_mod_3 == 0) ? 256 :

View File

@ -33,7 +33,7 @@ load_vector_int(BitStream& bit_stream, int nitems, std::vector<T>& vec,
{ {
vec.push_back(T()); 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) 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. // into the vec2 vector field of the ith item of vec1.
for (int i1 = 0; i1 < nitems1; ++i1) 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(); bit_stream.skipToNextByte();
@ -237,8 +237,8 @@ QPDF::readLinearizationData()
} }
// H: hint table offset/length for primary and overflow hint tables // H: hint table offset/length for primary and overflow hint tables
int H0_offset = H_items[0]; int H0_offset = H_items.at(0);
int H0_length = H_items[1]; int H0_length = H_items.at(1);
int H1_offset = 0; int H1_offset = 0;
int H1_length = 0; int H1_length = 0;
if (H_items.size() == 4) if (H_items.size() == 4)
@ -246,8 +246,8 @@ QPDF::readLinearizationData()
// Acrobat doesn't read or write these (as PDF 1.4), so we // Acrobat doesn't read or write these (as PDF 1.4), so we
// don't have a way to generate a test case. // don't have a way to generate a test case.
// QTC::TC("qpdf", "QPDF overflow hint table"); // QTC::TC("qpdf", "QPDF overflow hint table");
H1_offset = H_items[2]; H1_offset = H_items.at(2);
H1_length = H_items[3]; H1_length = H_items.at(3);
} }
// P: first page number // P: first page number
@ -470,7 +470,7 @@ QPDF::readHSharedObject(BitStream h)
1, &HSharedObjectEntry::signature_present); 1, &HSharedObjectEntry::signature_present);
for (int i = 0; i < nitems; ++i) 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 // Skip 128-bit MD5 hash. These are not supported by
// acrobat, so they should probably never be there. We // acrobat, so they should probably never be there. We
@ -512,7 +512,7 @@ QPDF::checkLinearizationInternal()
// O: object number of first page // O: object number of first page
std::vector<QPDFObjectHandle> const& pages = getAllPages(); 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"); QTC::TC("qpdf", "QPDF err /O mismatch");
errors.push_back("first page object (/O) mismatch"); errors.push_back("first page object (/O) mismatch");
@ -528,7 +528,7 @@ QPDF::checkLinearizationInternal()
for (int i = 0; i < npages; ++i) for (int i = 0; i < npages; ++i)
{ {
QPDFObjectHandle const& page = pages[i]; QPDFObjectHandle const& page = pages.at(i);
QPDFObjGen og(page.getObjGen()); QPDFObjGen og(page.getObjGen());
if (this->xref_table[og].getType() == 2) if (this->xref_table[og].getType() == 2)
{ {
@ -776,7 +776,7 @@ QPDF::checkHPageOffset(std::list<std::string>& errors,
unsigned int npages = pages.size(); unsigned int npages = pages.size();
int table_offset = adjusted_offset( int table_offset = adjusted_offset(
this->page_offset_hints.first_page_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); assert(this->xref_table.count(first_page_og) > 0);
int offset = getLinearizationOffset(first_page_og); int offset = getLinearizationOffset(first_page_og);
if (table_offset != offset) if (table_offset != offset)
@ -786,13 +786,13 @@ QPDF::checkHPageOffset(std::list<std::string>& errors,
for (unsigned int pageno = 0; pageno < npages; ++pageno) 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(); int first_object = page_og.getObj();
assert(this->xref_table.count(page_og) > 0); assert(this->xref_table.count(page_og) > 0);
offset = getLinearizationOffset(page_og); offset = getLinearizationOffset(page_og);
HPageOffsetEntry& he = this->page_offset_hints.entries[pageno]; HPageOffsetEntry& he = this->page_offset_hints.entries.at(pageno);
CHPageOffsetEntry& ce = this->c_page_offset_data.entries[pageno]; CHPageOffsetEntry& ce = this->c_page_offset_data.entries.at(pageno);
int h_nobjects = he.delta_nobjects + int h_nobjects = he.delta_nobjects +
this->page_offset_hints.min_nobjects; this->page_offset_hints.min_nobjects;
if (h_nobjects != ce.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) 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) if (shared_idx_to_obj.count(idx) == 0)
{ {
throw std::logic_error( throw std::logic_error(
@ -849,13 +849,13 @@ QPDF::checkHPageOffset(std::list<std::string>& errors,
for (int i = 0; i < ce.nshared_objects; ++i) 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) if (idx >= this->c_shared_object_data.nshared_total)
{ {
throw std::logic_error( throw std::logic_error(
"index out of bounds for shared object hint table"); "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); computed_shared.insert(obj);
} }
@ -923,7 +923,7 @@ QPDF::checkHSharedObject(std::list<std::string>& errors,
// The first nshared_first_page objects are consecutive // The first nshared_first_page objects are consecutive
// objects starting with the first page object. The rest are // objects starting with the first page object. The rest are
// consecutive starting from the first_shared_obj object. // 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) for (int i = 0; i < so.nshared_total; ++i)
{ {
if (i == so.nshared_first_page) if (i == so.nshared_first_page)
@ -937,7 +937,7 @@ QPDF::checkHSharedObject(std::list<std::string>& errors,
} }
else else
{ {
int obj = this->part8[0].getObjectID(); int obj = this->part8.at(0).getObjectID();
if (obj != so.first_shared_obj) if (obj != so.first_shared_obj)
{ {
errors.push_back( errors.push_back(
@ -965,7 +965,7 @@ QPDF::checkHSharedObject(std::list<std::string>& errors,
} }
idx_to_obj[i] = cur_object; 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 nobjects = se.nobjects_minus_one + 1;
int length = lengthNextN(cur_object, nobjects, errors); int length = lengthNextN(cur_object, nobjects, errors);
int h_length = so.min_group_length + se.delta_group_length; 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) for (int i1 = 0; i1 < this->linp.npages; ++i1)
{ {
HPageOffsetEntry& pe = t.entries[i1]; HPageOffsetEntry& pe = t.entries.at(i1);
*out_stream *out_stream
<< "Page " << i1 << ":" << std::endl << "Page " << i1 << ":" << std::endl
<< " nobjects: " << pe.delta_nobjects + t.min_nobjects << " nobjects: " << pe.delta_nobjects + t.min_nobjects
@ -1162,9 +1162,9 @@ QPDF::dumpHPageOffset()
for (int i2 = 0; i2 < pe.nshared_objects; ++i2) for (int i2 = 0; i2 < pe.nshared_objects; ++i2)
{ {
*out_stream << " identifier " << i2 << ": " *out_stream << " identifier " << i2 << ": "
<< pe.shared_identifiers[i2] << std::endl; << pe.shared_identifiers.at(i2) << std::endl;
*out_stream << " numerator " << i2 << ": " *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) 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 << "Shared Object " << i << ":" << std::endl;
*out_stream << " group length: " *out_stream << " group length: "
<< se.delta_group_length + t.min_group_length << std::endl; << 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. // will do the same.
// First, place the actual first page object itself. // 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)) if (! lc_first_page_private.count(first_page_og))
{ {
throw std::logic_error( 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"); "object not in lc_first_page_private");
} }
lc_first_page_private.erase(first_page_og); lc_first_page_private.erase(first_page_og);
this->c_linp.first_page_object = pages[0].getObjectID(); this->c_linp.first_page_object = pages.at(0).getObjectID();
this->part6.push_back(pages[0]); this->part6.push_back(pages.at(0));
// The PDF spec "recommends" an order for the rest of the objects, // 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 // 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 // in garbage values for all the shared object identifiers on the
// first page. // 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 // 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 // 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)) if (! lc_other_page_private.count(page_og))
{ {
throw std::logic_error( 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"); QUtil::int_to_string(i) + " not in lc_other_page_private");
} }
lc_other_page_private.erase(page_og); 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, // Place all non-shared objects referenced by this page,
// updating the page object count for the hint table. // 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); ObjUser ou(ObjUser::ou_page, i);
assert(this->obj_user_to_objects.count(ou) > 0); 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); lc_other_page_private.erase(og);
this->part7.push_back(objGenToIndirect(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. // thumbnail hint tables.
for (unsigned int i = 0; i < npages; ++i) 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); thumb = getUncompressedObject(thumb, object_stream_data);
if (! thumb.isNull()) if (! thumb.isNull())
{ {
@ -1758,7 +1758,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
if (! this->part8.empty()) if (! this->part8.empty())
{ {
this->c_shared_object_data.first_shared_obj = this->c_shared_object_data.first_shared_obj =
this->part8[0].getObjectID(); this->part8.at(0).getObjectID();
for (std::vector<QPDFObjectHandle>::iterator iter = for (std::vector<QPDFObjectHandle>::iterator iter =
this->part8.begin(); this->part8.begin();
iter != this->part8.end(); ++iter) 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) 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); ObjUser ou(ObjUser::ou_page, i);
assert(this->obj_user_to_objects.count(ou) > 0); assert(this->obj_user_to_objects.count(ou) > 0);
std::set<QPDFObjGen> const& ogs = this->obj_user_to_objects[ou]; 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 // Calculate minimum and maximum values for number of objects per
// page and page length. // page and page length.
int min_nobjects = cphe[0].nobjects; int min_nobjects = cphe.at(0).nobjects;
int max_nobjects = min_nobjects; int max_nobjects = min_nobjects;
int min_length = outputLengthNextN( 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_length = min_length;
int max_shared = cphe[0].nshared_objects; int max_shared = cphe.at(0).nshared_objects;
HPageOffset& ph = this->page_offset_hints; HPageOffset& ph = this->page_offset_hints;
std::vector<HPageOffsetEntry>& phe = ph.entries; std::vector<HPageOffsetEntry>& phe = ph.entries;
@ -1912,10 +1912,10 @@ QPDF::calculateHPageOffset(
// Repeat calculations for page 0 so we can assign to phe[i] // Repeat calculations for page 0 so we can assign to phe[i]
// without duplicating those assignments. // without duplicating those assignments.
int nobjects = cphe[i].nobjects; int nobjects = cphe.at(i).nobjects;
int length = outputLengthNextN( int length = outputLengthNextN(
pages[i].getObjectID(), nobjects, lengths, obj_renumber); pages.at(i).getObjectID(), nobjects, lengths, obj_renumber);
int nshared = cphe[i].nshared_objects; int nshared = cphe.at(i).nshared_objects;
min_nobjects = std::min(min_nobjects, nobjects); min_nobjects = std::min(min_nobjects, nobjects);
max_nobjects = std::max(max_nobjects, nobjects); max_nobjects = std::max(max_nobjects, nobjects);
@ -1923,13 +1923,13 @@ QPDF::calculateHPageOffset(
max_length = std::max(max_length, length); max_length = std::max(max_length, length);
max_shared = std::max(max_shared, nshared); max_shared = std::max(max_shared, nshared);
phe[i].delta_nobjects = nobjects; phe.at(i).delta_nobjects = nobjects;
phe[i].delta_page_length = length; phe.at(i).delta_page_length = length;
phe[i].nshared_objects = nshared; phe.at(i).nshared_objects = nshared;
} }
ph.min_nobjects = min_nobjects; 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; int out_page0_id = (*(obj_renumber.find(in_page0_id))).second;
ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset(); ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset();
ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects); ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects);
@ -1951,17 +1951,17 @@ QPDF::calculateHPageOffset(
for (unsigned int i = 0; i < npages; ++i) for (unsigned int i = 0; i < npages; ++i)
{ {
// Adjust delta entries // Adjust delta entries
assert(phe[i].delta_nobjects >= min_nobjects); assert(phe.at(i).delta_nobjects >= min_nobjects);
assert(phe[i].delta_page_length >= min_length); assert(phe.at(i).delta_page_length >= min_length);
phe[i].delta_nobjects -= min_nobjects; phe.at(i).delta_nobjects -= min_nobjects;
phe[i].delta_page_length -= min_length; phe.at(i).delta_page_length -= min_length;
phe[i].delta_content_length = phe[i].delta_page_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( phe.at(i).shared_identifiers.push_back(
cphe[i].shared_identifiers[j]); cphe.at(i).shared_identifiers.at(j));
phe[i].shared_numerators.push_back(0); phe.at(i).shared_numerators.push_back(0);
} }
} }
} }
@ -1979,18 +1979,18 @@ QPDF::calculateHSharedObject(
soe.clear(); soe.clear();
int min_length = outputLengthNextN( int min_length = outputLengthNextN(
csoe[0].object, 1, lengths, obj_renumber); csoe.at(0).object, 1, lengths, obj_renumber);
int max_length = min_length; int max_length = min_length;
for (int i = 0; i < cso.nshared_total; ++i) for (int i = 0; i < cso.nshared_total; ++i)
{ {
// Assign absolute numbers to deltas; adjust later // Assign absolute numbers to deltas; adjust later
int length = outputLengthNextN( 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); min_length = std::min(min_length, length);
max_length = std::max(max_length, length); max_length = std::max(max_length, length);
soe.push_back(HSharedObjectEntry()); 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)) 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) for (int i = 0; i < cso.nshared_total; ++i)
{ {
// Adjust deltas // Adjust deltas
assert(soe[i].delta_group_length >= min_length); assert(soe.at(i).delta_group_length >= min_length);
soe[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) 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 // The PDF spec says that each hint table starts at a byte
// boundary. Each "row" actually must start on a byte boundary. // 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. // from the vec2 vector field of the ith item of vec1.
for (int i1 = 0; i1 < nitems1; ++i1) 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(); w.flush();
@ -2151,7 +2151,7 @@ QPDF::writeHSharedObject(BitWriter& w)
for (int i = 0; i < nitems; ++i) for (int i = 0; i < nitems; ++i)
{ {
// If signature were present, we'd have to write a 128-bit hash. // 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, write_vector_int(w, nitems, entries,
t.nbits_nobjects, t.nbits_nobjects,

View File

@ -91,7 +91,7 @@ QPDF::optimize(std::map<int, int> const& object_stream_data,
for (int pageno = 0; pageno < n; ++pageno) for (int pageno = 0; pageno < n; ++pageno)
{ {
updateObjectMaps(ObjUser(ObjUser::ou_page, pageno), updateObjectMaps(ObjUser(ObjUser::ou_page, pageno),
this->all_pages[pageno]); this->all_pages.at(pageno));
} }
// Traverse document-level items // Traverse document-level items

View File

@ -114,8 +114,8 @@ QPDF::flattenPagesTree()
for (int pos = 0; pos < len; ++pos) for (int pos = 0; pos < len; ++pos)
{ {
// populate pageobj_to_pages_pos and fix parent pointer // populate pageobj_to_pages_pos and fix parent pointer
insertPageobjToPage(this->all_pages[pos], pos, true); insertPageobjToPage(this->all_pages.at(pos), pos, true);
this->all_pages[pos].replaceKey("/Parent", pages); this->all_pages.at(pos).replaceKey("/Parent", pages);
} }
pages.replaceKey("/Kids", QPDFObjectHandle::newArray(this->all_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)); assert(this->all_pages.size() == static_cast<size_t>(npages));
for (int i = pos + 1; i < npages; ++i) 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); insertPageobjToPage(newpage, pos, true);
assert(this->pageobj_to_pages_pos.size() == static_cast<size_t>(npages)); 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)); assert(this->pageobj_to_pages_pos.size() == static_cast<size_t>(npages));
for (int i = pos; i < npages; ++i) for (int i = pos; i < npages; ++i)
{ {
insertPageobjToPage(this->all_pages[i], i, false); insertPageobjToPage(this->all_pages.at(i), i, false);
} }
} }

View File

@ -201,7 +201,7 @@ QUtil::hex_encode(std::string const& input)
for (unsigned int i = 0; i < input.length(); ++i) for (unsigned int i = 0; i < input.length(); ++i)
{ {
result += QUtil::int_to_string_base( 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; return result;
} }

View File

@ -441,7 +441,7 @@ static std::vector<int> parse_numrange(char const* range, int max,
p = 0; p = 0;
for (size_t i = 0; i < work.size(); i += 2) 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 // max == 0 means we don't know the max and are just
// testing for valid syntax. // testing for valid syntax.
if ((max > 0) && ((num < 1) || (num > max))) 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) if (i == 0)
{ {
result.push_back(work[i]); result.push_back(work.at(i));
} }
else else
{ {
int separator = work[i-1]; int separator = work.at(i-1);
if (separator == comma) if (separator == comma)
{ {
result.push_back(num); result.push_back(num);
@ -1664,7 +1664,7 @@ int main(int argc, char* argv[])
// Pages are specified from 1 but numbered // Pages are specified from 1 but numbered
// from 0 in the vector // from 0 in the vector
int pageno = *pageno_iter - 1; 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) if (page_data.qpdf == &pdf)
{ {
// This is a page from the original file. // 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) if (selected_from_orig.count(pageno) == 0)
{ {
pdf.replaceObject(orig_pages[pageno].getObjGen(), pdf.replaceObject(orig_pages.at(pageno).getObjGen(),
QPDFObjectHandle::newNull()); QPDFObjectHandle::newNull());
} }
} }

View File

@ -603,10 +603,10 @@ void runtest(int n, char const* filename1, char const* arg2)
else if (n == 10) else if (n == 10)
{ {
std::vector<QPDFObjectHandle> pages = pdf.getAllPages(); std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
pages[0].addPageContents( pages.at(0).addPageContents(
QPDFObjectHandle::newStream( QPDFObjectHandle::newStream(
&pdf, "BT /F1 12 Tf 72 620 Td (Baked) Tj ET\n"), true); &pdf, "BT /F1 12 Tf 72 620 Td (Baked) Tj ET\n"), true);
pages[0].addPageContents( pages.at(0).addPageContents(
QPDFObjectHandle::newStream( QPDFObjectHandle::newStream(
&pdf, "BT /F1 18 Tf 72 520 Td (Mashed) Tj ET\n"), false); &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"); " not called 4-page file");
} }
// Swap pages 2 and 3 // 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 // Replace object and swap objects
QPDFObjectHandle trailer = pdf.getTrailer(); QPDFObjectHandle trailer = pdf.getTrailer();
QPDFObjectHandle qdict = trailer.getKey("/QDict"); 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 = std::map<std::string, QPDFObjectHandle> dict_items =
qarray.getDictAsMap(); qarray.getDictAsMap();
if ((array_elements.size() == 1) && if ((array_elements.size() == 1) &&
(array_elements[0].getName() == "/Array") && (array_elements.at(0).getName() == "/Array") &&
(dict_items.size() == 1) && (dict_items.size() == 1) &&
(dict_items["/NewDict"].getIntValue() == 2)) (dict_items["/NewDict"].getIntValue() == 2))
{ {
@ -738,12 +738,12 @@ void runtest(int n, char const* filename1, char const* arg2)
assert(pages.size() == 9); assert(pages.size() == 9);
pdf.removePage(*pages.begin()); // original page 0 pdf.removePage(*pages.begin()); // original page 0
assert(pages.size() == 8); assert(pages.size() == 8);
checkPageContents(pages[4], "Original page 5"); checkPageContents(pages.at(4), "Original page 5");
pdf.removePage(pages[4]); // original page 5 pdf.removePage(pages.at(4)); // original page 5
assert(pages.size() == 7); assert(pages.size() == 7);
checkPageContents(pages[4], "Original page 6"); checkPageContents(pages.at(4), "Original page 6");
checkPageContents(pages[0], "Original page 1"); checkPageContents(pages.at(0), "Original page 1");
checkPageContents(pages[6], "Original page 8"); checkPageContents(pages.at(6), "Original page 8");
// Insert pages // Insert pages
@ -760,7 +760,7 @@ void runtest(int n, char const* filename1, char const* arg2)
// dictionary and modify it. Using the results of // dictionary and modify it. Using the results of
// getDictAsMap to create a new dictionary effectively creates // getDictAsMap to create a new dictionary effectively creates
// a shallow copy. // a shallow copy.
QPDFObjectHandle page_template = pages[0]; QPDFObjectHandle page_template = pages.at(0);
std::vector<QPDFObjectHandle> new_pages; std::vector<QPDFObjectHandle> new_pages;
for (std::vector<QPDFObjectHandle>::iterator iter = contents.begin(); for (std::vector<QPDFObjectHandle>::iterator iter = contents.begin();
iter != contents.end(); ++iter) iter != contents.end(); ++iter)
@ -781,25 +781,25 @@ void runtest(int n, char const* filename1, char const* arg2)
} }
// Now insert the pages // Now insert the pages
pdf.addPage(new_pages[0], true); pdf.addPage(new_pages.at(0), true);
checkPageContents(pages[0], "New page 1"); checkPageContents(pages.at(0), "New page 1");
pdf.addPageAt(new_pages[1], true, pages[0]); pdf.addPageAt(new_pages.at(1), true, pages.at(0));
assert(pages[0].getObjGen() == new_pages[1].getObjGen()); assert(pages.at(0).getObjGen() == new_pages.at(1).getObjGen());
pdf.addPageAt(new_pages[2], true, pages[5]); pdf.addPageAt(new_pages.at(2), true, pages.at(5));
assert(pages[5].getObjGen() == new_pages[2].getObjGen()); assert(pages.at(5).getObjGen() == new_pages.at(2).getObjGen());
pdf.addPageAt(new_pages[3], false, pages[5]); pdf.addPageAt(new_pages.at(3), false, pages.at(5));
assert(pages[6].getObjGen() == new_pages[3].getObjGen()); assert(pages.at(6).getObjGen() == new_pages.at(3).getObjGen());
assert(pages.size() == 11); assert(pages.size() == 11);
pdf.addPage(new_pages[4], false); pdf.addPage(new_pages.at(4), false);
assert(pages[11].getObjGen() == new_pages[4].getObjGen()); assert(pages.at(11).getObjGen() == new_pages.at(4).getObjGen());
pdf.addPageAt(new_pages[5], false, pages.back()); pdf.addPageAt(new_pages.at(5), false, pages.back());
assert(pages.size() == 13); assert(pages.size() == 13);
checkPageContents(pages[0], "New page 0"); checkPageContents(pages.at(0), "New page 0");
checkPageContents(pages[1], "New page 1"); checkPageContents(pages.at(1), "New page 1");
checkPageContents(pages[5], "New page 5"); checkPageContents(pages.at(5), "New page 5");
checkPageContents(pages[6], "New page 6"); checkPageContents(pages.at(6), "New page 6");
checkPageContents(pages[11], "New page 11"); checkPageContents(pages.at(11), "New page 11");
checkPageContents(pages[12], "New page 12"); checkPageContents(pages.at(12), "New page 12");
// Exercise writing to FILE* // Exercise writing to FILE*
FILE* out = QUtil::safe_fopen("a.pdf", "wb"); 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 contents = createPageContents(pdf, "New page 10");
QPDFObjectHandle page = QPDFObjectHandle page =
pdf.makeIndirectObject( pdf.makeIndirectObject(
QPDFObjectHandle(all_pages[0]).shallowCopy()); QPDFObjectHandle(all_pages.at(0)).shallowCopy());
page.replaceKey("/Contents", contents); page.replaceKey("/Contents", contents);
// Insert the page manually. // 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 // The input file to this test case is broken to exercise an
// error condition. // error condition.
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages(); 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; std::cout << "you can't see this" << std::endl;
} }
else if (n == 18) 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 // Remove pages from various places, checking to make sure
// that our pages reference is getting updated. // that our pages reference is getting updated.
assert(pages.size() == 10); assert(pages.size() == 10);
QPDFObjectHandle page5 = pages[5]; QPDFObjectHandle page5 = pages.at(5);
pdf.removePage(page5); pdf.removePage(page5);
pdf.addPage(page5, false); pdf.addPage(page5, false);
assert(pages.size() == 10); 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(); std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
// Try to insert a page that's already there. // 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; std::cout << "you can't see this" << std::endl;
} }
else if (n == 20) else if (n == 20)
@ -893,7 +893,7 @@ void runtest(int n, char const* filename1, char const* arg2)
{ {
// Try to shallow copy a stream // Try to shallow copy a stream
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages(); std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
QPDFObjectHandle page = pages[0]; QPDFObjectHandle page = pages.at(0);
QPDFObjectHandle contents = page.getKey("/Contents"); QPDFObjectHandle contents = page.getKey("/Contents");
contents.shallowCopy(); contents.shallowCopy();
std::cout << "you can't see this" << std::endl; 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 // Try to remove a page we don't have
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages(); std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
QPDFObjectHandle page = pages[0]; QPDFObjectHandle page = pages.at(0);
pdf.removePage(page); pdf.removePage(page);
pdf.removePage(page); pdf.removePage(page);
std::cout << "you can't see this" << std::endl; 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; QPDF final;
final.processFile("b.pdf", "user"); final.processFile("b.pdf", "user");
std::vector<QPDFObjectHandle> pages = pdf.getAllPages(); std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
std::string orig_contents = getPageContents(pages[0]); std::string orig_contents = getPageContents(pages.at(0));
pages = final.getAllPages(); pages = final.getAllPages();
std::string new_contents = getPageContents(pages[0]); std::string new_contents = getPageContents(pages.at(0));
if (orig_contents != new_contents) if (orig_contents != new_contents)
{ {
std::cout << "oops -- page contents don't match" << std::endl 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; bool is_binary = false;
for (size_t i = 0; i < data.size(); ++i) 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; is_binary = true;
break; 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 < std::min(data.size(), static_cast<size_t>(20));
++i) ++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 else
{ {

View File

@ -286,8 +286,8 @@ static void check_pdf(char const* filename)
{ {
int pageno = i + 1; int pageno = i + 1;
std::cout << "page " << pageno << " of " << npages << std::endl; std::cout << "page " << pageno << " of " << npages << std::endl;
check_page_contents(pageno, pages[i]); check_page_contents(pageno, pages.at(i));
check_image(pageno, pages[i]); check_image(pageno, pages.at(i));
} }
} }