Use QPDFObjectHandle::asInteger in the library

This commit is contained in:
m-holger 2024-03-19 10:23:35 +00:00
parent f2fc1d3db8
commit 6b5fc3278d
18 changed files with 155 additions and 221 deletions

View File

@ -686,7 +686,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
if (!m->trailer.isInitialized()) {
throw damagedPDF("", 0, "unable to find trailer while reading xref");
}
int size = m->trailer.getKey("/Size").getIntValueAsInt();
int size = m->trailer.getKey("/Size").asInteger();
int max_obj = 0;
if (!m->xref_table.empty()) {
max_obj = (*(m->xref_table.rbegin())).first.getObj();
@ -912,17 +912,13 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
}
}
if (cur_trailer.hasKey("/XRefStm")) {
if (m->ignore_xref_streams) {
QTC::TC("qpdf", "QPDF ignoring XRefStm in trailer");
} else {
if (cur_trailer.getKey("/XRefStm").isInteger()) {
// Read the xref stream but disregard any return value -- we'll use our trailer's
// /Prev key instead of the xref stream's.
(void)read_xrefStream(cur_trailer.getKey("/XRefStm").getIntValue());
} else {
throw damagedPDF("xref stream", xref_offset, "invalid /XRefStm");
}
if (!m->ignore_xref_streams) {
if (auto offset = cur_trailer.getKey("/XRefStm").asInteger()) {
// Read the xref stream but disregard any return value -- we'll use our trailer's
// /Prev key instead of the xref stream's.
(void)read_xrefStream(offset);
} else if (!offset.null()) {
throw damagedPDF("xref stream", xref_offset, "invalid /XRefStm");
}
}
@ -931,15 +927,12 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
insertFreeXrefEntry(og);
}
if (cur_trailer.hasKey("/Prev")) {
if (!cur_trailer.getKey("/Prev").isInteger()) {
QTC::TC("qpdf", "QPDF trailer prev not integer");
throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer");
}
QTC::TC("qpdf", "QPDF prev key in trailer dictionary");
xref_offset = cur_trailer.getKey("/Prev").getIntValue();
if (auto prev = cur_trailer.getKey("/Prev").asInteger(true)) {
QTC::TC("qpdf", "QPDF prev key in trailer dictionary", prev.null() ? 0 : 1);
return prev;
} else {
xref_offset = 0;
QTC::TC("qpdf", "QPDF trailer prev not integer");
throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer");
}
return xref_offset;
@ -987,7 +980,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
size_t entry_size = 0;
int max_bytes = sizeof(qpdf_offset_t);
for (int i = 0; i < 3; ++i) {
W[i] = W_obj.getArrayItem(i).getIntValueAsInt();
W[i] = W_obj.getArrayItem(i).asInteger();
if (W[i] > max_bytes) {
throw damagedPDF(
"xref stream",
@ -1013,8 +1006,8 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
"values");
}
for (int i = 0; i < n_index; ++i) {
if (Index_obj.getArrayItem(i).isInteger()) {
indx.push_back(Index_obj.getArrayItem(i).getIntValue());
if (auto index = Index_obj.getArrayItem(i).asInteger()) {
indx.emplace_back(index);
} else {
throw damagedPDF(
"xref stream",
@ -1026,9 +1019,8 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
QTC::TC("qpdf", "QPDF xref /Index is array", n_index == 2 ? 0 : 1);
} else {
QTC::TC("qpdf", "QPDF xref /Index is null");
long long size = dict.getKey("/Size").getIntValue();
indx.push_back(0);
indx.push_back(size);
indx.emplace_back(0);
indx.emplace_back(dict.getKey("/Size").asInteger());
}
size_t num_entries = 0;
@ -1131,18 +1123,12 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
setTrailer(dict);
}
if (dict.hasKey("/Prev")) {
if (!dict.getKey("/Prev").isInteger()) {
throw damagedPDF(
"xref stream", "/Prev key in xref stream dictionary is not an integer");
}
if (auto prev = dict.getKey("/Prev").asInteger(true)) {
QTC::TC("qpdf", "QPDF prev key in xref stream dictionary");
xref_offset = dict.getKey("/Prev").getIntValue();
return prev;
} else {
xref_offset = 0;
throw damagedPDF("xref stream", "/Prev key in xref stream dictionary is not an integer");
}
return xref_offset;
}
void
@ -1368,25 +1354,22 @@ QPDF::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset)
size_t length = 0;
try {
auto length_obj = object.getKey("/Length");
if (!length_obj.isInteger()) {
if (length_obj.isNull()) {
QTC::TC("qpdf", "QPDF stream without length");
throw damagedPDF(offset, "stream dictionary lacks /Length key");
if (auto length_obj = object.getKey("/Length").asInteger()) {
length = toS(length_obj.value());
// Seek in two steps to avoid potential integer overflow
m->file->seek(stream_offset, SEEK_SET);
m->file->seek(toO(length), SEEK_CUR);
if (!readToken(m->file).isWord("endstream")) {
QTC::TC("qpdf", "QPDF missing endstream");
throw damagedPDF("expected endstream");
}
} else if (length_obj.null()) {
QTC::TC("qpdf", "QPDF stream without length");
throw damagedPDF(offset, "stream dictionary lacks /Length key");
} else {
QTC::TC("qpdf", "QPDF stream length not integer");
throw damagedPDF(offset, "/Length key in stream dictionary is not an integer");
}
length = toS(length_obj.getUIntValue());
// Seek in two steps to avoid potential integer overflow
m->file->seek(stream_offset, SEEK_SET);
m->file->seek(toO(length), SEEK_CUR);
if (!readToken(m->file).isWord("endstream")) {
QTC::TC("qpdf", "QPDF missing endstream");
throw damagedPDF("expected endstream");
}
} catch (QPDFExc& e) {
if (m->attempt_recovery) {
warn(e);
@ -1778,15 +1761,14 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
warn(damagedPDF(
"supposed object stream " + std::to_string(obj_stream_number) + " has wrong type"));
}
if (!(dict.getKey("/N").isInteger() && dict.getKey("/First").isInteger())) {
int n{0};
long long first{0};
if (!(dict.getKey("/N").asInteger().assign_to(n) &&
dict.getKey("/First").asInteger().assign_to(first))) {
throw damagedPDF(
("object stream " + std::to_string(obj_stream_number) + " has incorrect keys"));
}
int n = dict.getKey("/N").getIntValueAsInt();
int first = dict.getKey("/First").getIntValueAsInt();
std::map<int, int> offsets;
std::shared_ptr<Buffer> bp = obj_stream.getStreamData(qpdf_dl_specialized);
@ -2328,21 +2310,11 @@ QPDF::getPDFVersion() const
int
QPDF::getExtensionLevel()
{
int result = 0;
QPDFObjectHandle obj = getRoot();
if (obj.hasKey("/Extensions")) {
obj = obj.getKey("/Extensions");
if (obj.isDictionary() && obj.hasKey("/ADBE")) {
obj = obj.getKey("/ADBE");
if (obj.isDictionary() && obj.hasKey("/ExtensionLevel")) {
obj = obj.getKey("/ExtensionLevel");
if (obj.isInteger()) {
result = obj.getIntValueAsInt();
}
}
}
}
return result;
return getRoot()
.getKey("/Extensions")
.getKeyIfDict("/ADBE")
.getKeyIfDict("/ExtensionLevel")
.asInteger(true);
}
QPDFObjectHandle

View File

@ -740,9 +740,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
if (acroform.getKey("/DA").isString()) {
default_da = acroform.getKey("/DA").getUTF8Value();
}
if (acroform.getKey("/Q").isInteger()) {
default_q = acroform.getKey("/Q").getIntValueAsInt();
}
acroform.getKey("/Q").asInteger().assign_to(default_q);
}
if (from_acroform.isDictionary()) {
if (from_acroform.getKey("/DR").isDictionary()) {
@ -755,9 +753,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
if (from_acroform.getKey("/DA").isString()) {
from_default_da = from_acroform.getKey("/DA").getUTF8Value();
}
if (from_acroform.getKey("/Q").isInteger()) {
from_default_q = from_acroform.getKey("/Q").getIntValueAsInt();
}
from_acroform.getKey("/Q").asInteger().assign_to(from_default_q);
}
if (from_default_da != default_da) {
override_da = true;

View File

@ -42,8 +42,8 @@ QPDFAnnotationObjectHelper::getAppearanceState()
int
QPDFAnnotationObjectHelper::getFlags()
{
QPDFObjectHandle flags_obj = this->oh.getKey("/F");
return flags_obj.isInteger() ? flags_obj.getIntValueAsInt() : 0;
auto flags_obj = this->oh.getKey("/F").asInteger();
return flags_obj ? flags_obj : 0;
}
QPDFObjectHandle

View File

@ -57,11 +57,8 @@ QPDFEFStreamObjectHelper::getModDate()
size_t
QPDFEFStreamObjectHelper::getSize()
{
auto val = getParam("/Size");
if (val.isInteger()) {
return QIntC::to_size(val.getUIntValueAsUInt());
}
return 0;
auto val = getParam("/Size").asInteger();
return val ? QIntC::to_size(val.value()) : 0;
}
std::string

View File

@ -213,25 +213,19 @@ QPDFFormFieldObjectHelper::getDefaultAppearance()
int
QPDFFormFieldObjectHelper::getQuadding()
{
QPDFObjectHandle fv = getInheritableFieldValue("/Q");
bool looked_in_acroform = false;
if (!fv.isInteger()) {
fv = getFieldFromAcroForm("/Q");
looked_in_acroform = true;
if (auto fv = getInheritableFieldValue("/Q").asInteger()) {
QTC::TC("qpdf", "QPDFFormFieldObjectHelper Q present");
return fv;
} else {
QTC::TC("qpdf", "QPDFFormFieldObjectHelper Q present looked");
return getFieldFromAcroForm("/Q").asInteger(true);
}
int result = 0;
if (fv.isInteger()) {
QTC::TC("qpdf", "QPDFFormFieldObjectHelper Q present", looked_in_acroform ? 0 : 1);
result = QIntC::to_int(fv.getIntValue());
}
return result;
}
int
QPDFFormFieldObjectHelper::getFlags()
{
QPDFObjectHandle f = getInheritableFieldValue("/Ff");
return f.isInteger() ? f.getIntValueAsInt() : 0;
return getInheritableFieldValue("/Ff").asInteger(true);
}
bool

View File

@ -130,8 +130,8 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
}
return result;
}
QPDFObjectHandle components_obj = dict.getKey("/BitsPerComponent");
if (!(components_obj.isInteger() && (components_obj.getIntValue() == 8))) {
auto components_obj = dict.getKey("/BitsPerComponent").asInteger();
if (!(components_obj && (components_obj.value() == 8))) {
QTC::TC("qpdf", "QPDFJob image optimize bits per component");
if (!description.empty()) {
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
@ -144,14 +144,14 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
// Files have been seen in the wild whose width and height are floating point, which is goofy,
// but we can deal with it.
JDIMENSION w = 0;
if (w_obj.isInteger()) {
w = w_obj.getUIntValueAsUInt();
if (auto w_int = w_obj.asInteger()) {
w = w_int;
} else {
w = static_cast<JDIMENSION>(w_obj.getNumericValue());
}
JDIMENSION h = 0;
if (h_obj.isInteger()) {
h = h_obj.getUIntValueAsUInt();
if (auto h_int = h_obj.asInteger()) {
h = h_int;
} else {
h = static_cast<JDIMENSION>(h_obj.getNumericValue());
}
@ -216,7 +216,7 @@ ImageOptimizer::evaluate(std::string const& description)
if (!image.pipeStreamData(p.get(), 0, qpdf_dl_specialized)) {
return false;
}
long long orig_length = image.getDict().getKey("/Length").getIntValue();
long long orig_length = image.getDict().getKey("/Length").asInteger();
if (c.getCount() >= orig_length) {
QTC::TC("qpdf", "QPDFJob image optimize no shrink");
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
@ -858,8 +858,8 @@ QPDFJob::doShowPages(QPDF& pdf)
std::string const& name = iter2.first;
QPDFObjectHandle image = iter2.second;
QPDFObjectHandle dict = image.getDict();
int width = dict.getKey("/Width").getIntValueAsInt();
int height = dict.getKey("/Height").getIntValueAsInt();
int width = dict.getKey("/Width").asInteger();
int height = dict.getKey("/Height").asInteger();
cout << " " << name << ": " << image.unparse() << ", " << width << " x "
<< height << "\n";
}
@ -1651,7 +1651,7 @@ QPDFJob::doInspection(QPDF& pdf)
}
if (m->show_npages) {
QTC::TC("qpdf", "QPDFJob npages");
cout << pdf.getRoot().getKey("/Pages").getKey("/Count").getIntValue() << "\n";
cout << pdf.getRoot().getKey("/Pages").getKey("/Count").asInteger().value() << "\n";
}
if (m->show_encryption) {
showEncryption(pdf);
@ -3081,10 +3081,9 @@ QPDFJob::writeOutfile(QPDF& pdf)
try {
QUtil::remove_file(backup.c_str());
} catch (QPDFSystemError& e) {
*m->log->getError()
<< m->message_prefix << ": unable to delete original file (" << e.what() << ");"
<< " original file left in " << backup
<< ", but the input was successfully replaced\n";
*m->log->getError() << m->message_prefix << ": unable to delete original file ("
<< e.what() << ");" << " original file left in " << backup
<< ", but the input was successfully replaced\n";
}
}
}

View File

@ -22,12 +22,14 @@ namespace
int
compareKeys(QPDFObjectHandle a, QPDFObjectHandle b) const override
{
if (!(keyValid(a) && keyValid(b))) {
auto ai = a.asInteger();
auto bi = b.asInteger();
if (!(ai && bi)) {
// We don't call this without calling keyValid first
throw std::logic_error("comparing invalid keys");
}
auto as = a.getIntValue();
auto bs = b.getIntValue();
auto as = ai.value();
auto bs = bi.value();
return ((as < bs) ? -1 : (as > bs) ? 1 : 0);
}
};
@ -91,7 +93,7 @@ QPDFNumberTreeObjectHelper::iterator::updateIValue()
{
if (impl->valid()) {
auto p = *impl;
this->ivalue.first = p->first.getIntValue();
this->ivalue.first = p->first.asInteger();
this->ivalue.second = p->second;
} else {
this->ivalue.first = 0;

View File

@ -83,11 +83,7 @@ QPDFOutlineObjectHelper::getDestPage()
int
QPDFOutlineObjectHelper::getCount()
{
int count = 0;
if (this->oh.hasKey("/Count")) {
count = this->oh.getKey("/Count").getIntValueAsInt();
}
return count;
return this->oh.getKey("/Count").asInteger(true);
}
std::string

View File

@ -88,11 +88,7 @@ QPDFPageDocumentHelper::flattenAnnotationsForPage(
std::vector<QPDFAnnotationObjectHelper> annots = page.getAnnotations();
std::vector<QPDFObjectHandle> new_annots;
std::string new_content;
int rotate = 0;
QPDFObjectHandle rotate_obj = page.getObjectHandle().getKey("/Rotate");
if (rotate_obj.isInteger() && rotate_obj.getIntValue()) {
rotate = rotate_obj.getIntValueAsInt();
}
int rotate = page.getObjectHandle().getKey("/Rotate").asInteger(true);
int next_fx = 1;
for (auto& aoh: annots) {
QPDFObjectHandle as = aoh.getAppearanceStream("/N");

View File

@ -36,11 +36,8 @@ QPDFPageLabelDocumentHelper::getLabelForPage(long long page_idx)
}
QPDFObjectHandle S = label.getKey("/S"); // type (D, R, r, A, a)
QPDFObjectHandle P = label.getKey("/P"); // prefix
QPDFObjectHandle St = label.getKey("/St"); // starting number
long long start = 1;
if (St.isInteger()) {
start = St.getIntValue();
}
auto St = label.getKey("/St").asInteger(); // starting number
long long start = St ? St : 1;
QIntC::range_check(start, offset);
start += offset;
result = QPDFObjectHandle::newDictionary();
@ -72,14 +69,14 @@ QPDFPageLabelDocumentHelper::getLabelsForPageRange(
bool skip_first = false;
if (size >= 2) {
QPDFObjectHandle last = new_labels.at(size - 1);
QPDFObjectHandle last_idx = new_labels.at(size - 2);
if (last_idx.isInteger() && last.isDictionary() &&
auto last_idx = new_labels.at(size - 2).asInteger();
auto st = label.getKey("/St").asInteger();
auto last_st = last.getKey("/St").asInteger();
if (last_idx && last.isDictionary() &&
(label.getKey("/S").unparse() == last.getKey("/S").unparse()) &&
(label.getKey("/P").unparse() == last.getKey("/P").unparse()) &&
label.getKey("/St").isInteger() && last.getKey("/St").isInteger()) {
long long int st_delta =
label.getKey("/St").getIntValue() - last.getKey("/St").getIntValue();
long long int idx_delta = new_start_idx - last_idx.getIntValue();
(label.getKey("/P").unparse() == last.getKey("/P").unparse()) && st && last_st) {
auto st_delta = st.value() - last_st.value();
auto idx_delta = new_start_idx - last_idx.value();
if (st_delta == idx_delta) {
QTC::TC("qpdf", "QPDFPageLabelDocumentHelper skip first");
skip_first = true;

View File

@ -667,14 +667,14 @@ QPDFPageObjectHelper::getMatrixForTransformations(bool invert)
if (!bbox.isRectangle()) {
return matrix;
}
QPDFObjectHandle rotate_obj = getAttribute("/Rotate", false);
auto rotate_obj = getAttribute("/Rotate", false).asInteger();
QPDFObjectHandle scale_obj = getAttribute("/UserUnit", false);
if (!(rotate_obj.isNull() && scale_obj.isNull())) {
if (!(rotate_obj.null() && scale_obj.isNull())) {
QPDFObjectHandle::Rectangle rect = bbox.getArrayAsRectangle();
double width = rect.urx - rect.llx;
double height = rect.ury - rect.lly;
double scale = (scale_obj.isNumber() ? scale_obj.getNumericValue() : 1.0);
int rotate = (rotate_obj.isInteger() ? rotate_obj.getIntValueAsInt() : 0);
int rotate = rotate_obj ? rotate_obj : 0;
if (invert) {
if (scale == 0.0) {
return matrix;
@ -863,12 +863,9 @@ QPDFPageObjectHelper::flattenRotation(QPDFAcroFormDocumentHelper* afdh)
{
QPDF& qpdf =
this->oh.getQPDF("QPDFPageObjectHelper::flattenRotation called with a direct object");
auto rotate_oh = this->oh.getKey("/Rotate");
int rotate = 0;
if (rotate_oh.isInteger()) {
rotate = rotate_oh.getIntValueAsInt();
}
if (!((rotate == 90) || (rotate == 180) || (rotate == 270))) {
auto rotate_key = this->oh.getKey("/Rotate").asInteger();
int rotate = rotate_key ? rotate_key : 0;
if (!(rotate == 90 || rotate == 180 || rotate == 270)) {
return;
}
auto mediabox = this->oh.getKey("/MediaBox");

View File

@ -656,10 +656,11 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf)
generateID();
m->id1 = trailer.getKey("/ID").getArrayItem(0).getStringValue();
QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
int V = encrypt.getKey("/V").getIntValueAsInt();
int V = encrypt.getKey("/V").asInteger();
int key_len = 5;
if (V > 1) {
key_len = encrypt.getKey("/Length").getIntValueAsInt() / 8;
key_len = encrypt.getKey("/Length").asInteger();
key_len /= 8;
}
if (encrypt.hasKey("/EncryptMetadata") && encrypt.getKey("/EncryptMetadata").isBool()) {
m->encrypt_metadata = encrypt.getKey("/EncryptMetadata").getBoolValue();
@ -687,9 +688,9 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf)
setEncryptionParametersInternal(
V,
encrypt.getKey("/R").getIntValueAsInt(),
encrypt.getKey("/R").asInteger(),
key_len,
static_cast<int>(encrypt.getKey("/P").getIntValue()),
static_cast<int>(encrypt.getKey("/P").asInteger().value()),
encrypt.getKey("/O").getStringValue(),
encrypt.getKey("/U").getStringValue(),
OE,
@ -1416,10 +1417,10 @@ QPDFWriter::unparseObject(
if (extensions.isInitialized()) {
QTC::TC("qpdf", "QPDFWriter preserve Extensions");
QPDFObjectHandle adbe = extensions.getKey("/ADBE");
auto ext_level = adbe.getKeyIfDict("/ExtensionLevel").asInteger();
if (adbe.isDictionary() &&
adbe.getKey("/BaseVersion").isNameAndEquals("/" + m->final_pdf_version) &&
adbe.getKey("/ExtensionLevel").isInteger() &&
(adbe.getKey("/ExtensionLevel").getIntValue() == m->final_extension_level)) {
ext_level && (static_cast<int>(ext_level) == m->final_extension_level)) {
QTC::TC("qpdf", "QPDFWriter preserve ADBE");
} else {
if (need_extensions_adbe) {

View File

@ -586,7 +586,7 @@ QPDF_Stream::pipeStreamData(
qpdf_offset_t actual_length = count.getCount();
qpdf_offset_t desired_length = 0;
if (success && this->stream_dict.hasKey("/Length")) {
desired_length = this->stream_dict.getKey("/Length").getIntValue();
desired_length = this->stream_dict.getKey("/Length").asInteger();
if (actual_length == desired_length) {
QTC::TC("qpdf", "QPDF_Stream pipe use stream provider");
} else {

View File

@ -766,21 +766,22 @@ QPDF::initializeEncryption()
m->file->getLastOffset(),
"file uses encryption SubFilters, which qpdf does not support");
}
if (!(encryption_dict.getKey("/V").isInteger() && encryption_dict.getKey("/R").isInteger() &&
int V{0};
int R{0};
long long p_temp{0};
if (!(encryption_dict.getKey("/V").asInteger().assign_to(V) &&
encryption_dict.getKey("/R").asInteger().assign_to(R) &&
encryption_dict.getKey("/O").isString() && encryption_dict.getKey("/U").isString() &&
encryption_dict.getKey("/P").isInteger())) {
encryption_dict.getKey("/P").asInteger().assign_to(p_temp))) {
throw damagedPDF(
"encryption dictionary",
"some encryption dictionary parameters are missing or the wrong "
"type");
}
int V = encryption_dict.getKey("/V").getIntValueAsInt();
int R = encryption_dict.getKey("/R").getIntValueAsInt();
std::string O = encryption_dict.getKey("/O").getStringValue();
std::string U = encryption_dict.getKey("/U").getStringValue();
int P = static_cast<int>(encryption_dict.getKey("/P").getIntValue());
int P = static_cast<int>(p_temp);
// If supporting new encryption R/V values, remember to update error message inside this if
// statement.
@ -840,8 +841,8 @@ QPDF::initializeEncryption()
} else if (V == 5) {
Length = 256;
} else {
if (encryption_dict.getKey("/Length").isInteger()) {
Length = encryption_dict.getKey("/Length").getIntValueAsInt();
if (auto l = encryption_dict.getKey("/Length").asInteger()) {
Length = l;
if ((Length % 8) || (Length < 40) || (Length > 128)) {
Length = 0;
}
@ -1249,12 +1250,9 @@ QPDF::isEncrypted(
if (m->encp->encrypted) {
QPDFObjectHandle trailer = getTrailer();
QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
QPDFObjectHandle Pkey = encrypt.getKey("/P");
QPDFObjectHandle Rkey = encrypt.getKey("/R");
QPDFObjectHandle Vkey = encrypt.getKey("/V");
P = static_cast<int>(Pkey.getIntValue());
R = Rkey.getIntValueAsInt();
V = Vkey.getIntValueAsInt();
P = static_cast<int>(static_cast<long long>(encrypt.getKey("/P").asInteger()));
R = encrypt.getKey("/R").asInteger();
V = encrypt.getKey("/V").asInteger();
stream_method = m->encp->cf_stream;
string_method = m->encp->cf_string;
file_method = m->encp->cf_file;

View File

@ -138,9 +138,8 @@ QPDF::isLinearized()
return false;
}
QPDFObjectHandle L = candidate.getKey("/L");
if (L.isInteger()) {
qpdf_offset_t Li = L.getIntValue();
if (auto L = candidate.getKey("/L").asInteger()) {
qpdf_offset_t Li = L;
m->file->seek(0, SEEK_END);
if (Li != m->file->tell()) {
QTC::TC("qpdf", "QPDF /L mismatch");
@ -168,30 +167,28 @@ QPDF::readLinearizationData()
// /L is read and stored in linp by isLinearized()
QPDFObjectHandle H = m->lindict.getKey("/H");
QPDFObjectHandle O = m->lindict.getKey("/O");
QPDFObjectHandle E = m->lindict.getKey("/E");
QPDFObjectHandle N = m->lindict.getKey("/N");
QPDFObjectHandle T = m->lindict.getKey("/T");
QPDFObjectHandle P = m->lindict.getKey("/P");
auto O = m->lindict.getKey("/O").asInteger();
auto E = m->lindict.getKey("/E").asInteger();
auto N = m->lindict.getKey("/N").asInteger();
auto T = m->lindict.getKey("/T").asInteger();
auto P = m->lindict.getKey("/P").asInteger(true);
if (!(H.isArray() && O.isInteger() && E.isInteger() && N.isInteger() && T.isInteger() &&
(P.isInteger() || P.isNull()))) {
if (!(H.isArray() && O && E && N && T && P)) {
throw damagedPDF(
"linearization dictionary",
"some keys in linearization dictionary are of the wrong type");
}
// Hint table array: offset length [ offset length ]
size_t n_H_items = toS(H.getArrayNItems());
int n_H_items = H.getArrayNItems();
if (!((n_H_items == 2) || (n_H_items == 4))) {
throw damagedPDF("linearization dictionary", "H has the wrong number of items");
}
std::vector<int> H_items;
for (size_t i = 0; i < n_H_items; ++i) {
QPDFObjectHandle oh(H.getArrayItem(toI(i)));
if (oh.isInteger()) {
H_items.push_back(oh.getIntValueAsInt());
for (int i = 0; i < n_H_items; ++i) {
if (auto h = H.getArrayItem(toI(i)).asInteger()) {
H_items.push_back(h);
} else {
throw damagedPDF("linearization dictionary", "some H items are of the wrong type");
}
@ -211,28 +208,22 @@ QPDF::readLinearizationData()
}
// P: first page number
int first_page = 0;
if (P.isInteger()) {
QTC::TC("qpdf", "QPDF P present in lindict");
first_page = P.getIntValueAsInt();
} else {
QTC::TC("qpdf", "QPDF P absent in lindict");
}
QTC::TC("qpdf", "QPDF P present in lindict", P.null() ? 0 : 1);
// Store linearization parameter data
// Various places in the code use linp.npages, which is initialized from N, to pre-allocate
// memory, so make sure it's accurate and bail right now if it's not.
if (N.getIntValue() != static_cast<long long>(getAllPages().size())) {
if (static_cast<long long>(N) != static_cast<long long>(getAllPages().size())) {
throw damagedPDF("linearization hint table", "/N does not match number of pages");
}
// file_size initialized by isLinearized()
m->linp.first_page_object = O.getIntValueAsInt();
m->linp.first_page_end = E.getIntValue();
m->linp.npages = N.getIntValueAsInt();
m->linp.xref_zero_offset = T.getIntValue();
m->linp.first_page = first_page;
m->linp.first_page_object = O;
m->linp.first_page_end = E;
m->linp.npages = N;
m->linp.xref_zero_offset = T;
m->linp.first_page = P;
m->linp.H_offset = H0_offset;
m->linp.H_length = H0_length;
@ -255,8 +246,8 @@ QPDF::readLinearizationData()
// /L page label
// Individual hint table offsets
QPDFObjectHandle HS = H0.getKey("/S"); // shared object
QPDFObjectHandle HO = H0.getKey("/O"); // outline
int HS = H0.getKey("/S").asInteger(); // shared object
auto HO = H0.getKey("/O").asInteger(); // outline
auto hbp = pb.getBufferSharedPointer();
Buffer* hb = hbp.get();
@ -265,18 +256,18 @@ QPDF::readLinearizationData()
readHPageOffset(BitStream(h_buf, h_size));
int HSi = HS.getIntValueAsInt();
if ((HSi < 0) || (toS(HSi) >= h_size)) {
if ((HS < 0) || (toS(HS) >= h_size)) {
throw damagedPDF("linearization hint table", "/S (shared object) offset is out of bounds");
}
readHSharedObject(BitStream(h_buf + HSi, h_size - toS(HSi)));
readHSharedObject(BitStream(h_buf + HS, h_size - toS(HS)));
if (HO.isInteger()) {
int HOi = HO.getIntValueAsInt();
if ((HOi < 0) || (toS(HOi) >= h_size)) {
if (HO) {
int HOi = HO;
auto HOs = toS(HOi);
if (HOi < 0 || HOs >= h_size) {
throw damagedPDF("linearization hint table", "/O (outline) offset is out of bounds");
}
readHGeneric(BitStream(h_buf + HOi, h_size - toS(HOi)), m->outline_hints);
readHGeneric(BitStream(h_buf + HOi, h_size - HOs), m->outline_hints);
}
}
@ -303,7 +294,7 @@ QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length)
if (length_obj.isIndirect()) {
QTC::TC("qpdf", "QPDF hint table length indirect");
// Force resolution
(void)length_obj.getIntValue();
(void)length_obj.isInteger();
ObjCache& oc2 = m->obj_cache[length_obj.getObjGen()];
min_end_offset = oc2.end_before_space;
max_end_offset = oc2.end_after_space;

View File

@ -290,7 +290,7 @@ QPDF::addPage(QPDFObjectHandle newpage, bool first)
if (first) {
insertPage(newpage, 0);
} else {
insertPage(newpage, getRoot().getKey("/Pages").getKey("/Count").getIntValueAsInt());
insertPage(newpage, getRoot().getKey("/Pages").getKey("/Count").asInteger());
}
}

View File

@ -28,10 +28,10 @@ SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms)
bool filterable = true;
std::set<std::string> keys = decode_parms.getKeys();
for (auto const& key: keys) {
QPDFObjectHandle value = decode_parms.getKey(key);
auto value = decode_parms.getKey(key).asInteger();
if (key == "/Predictor") {
if (value.isInteger()) {
this->predictor = value.getIntValueAsInt();
if (value) {
this->predictor = value;
if (!((this->predictor == 1) || (this->predictor == 2) ||
((this->predictor >= 10) && (this->predictor <= 15)))) {
filterable = false;
@ -40,23 +40,22 @@ SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms)
filterable = false;
}
} else if ((key == "/Columns") || (key == "/Colors") || (key == "/BitsPerComponent")) {
if (value.isInteger()) {
int val = value.getIntValueAsInt();
if (value) {
if (key == "/Columns") {
this->columns = val;
this->columns = value;
} else if (key == "/Colors") {
this->colors = val;
this->colors = value;
} else if (key == "/BitsPerComponent") {
this->bits_per_component = val;
this->bits_per_component = value;
}
} else {
filterable = false;
}
} else if (lzw && (key == "/EarlyChange")) {
if (value.isInteger()) {
int earlychange = value.getIntValueAsInt();
if (value) {
int earlychange = value;
this->early_code_change = (earlychange == 1);
if (!((earlychange == 0) || (earlychange == 1))) {
if (!(earlychange == 0 || earlychange == 1)) {
filterable = false;
}
} else {

View File

@ -6,8 +6,7 @@ QPDF check generation 1
QPDF check obj 1
QPDF hint table length indirect 0
QPDF hint table length direct 0
QPDF P absent in lindict 0
QPDF P present in lindict 0
QPDF P present in lindict 1
QPDF expected n n obj 0
QPDF /L mismatch 0
QPDF err /T mismatch 0
@ -79,9 +78,8 @@ QPDFObjectHandle makeDirect loop 0
QPDFObjectHandle copy stream 1
QPDF default for xref stream field 0 0
QPDF prev key in xref stream dictionary 0
QPDF prev key in trailer dictionary 0
QPDF prev key in trailer dictionary 1
QPDF found xref stream 0
QPDF ignoring XRefStm in trailer 0
QPDF xref deleted object 0
SF_FlateLzwDecode PNG filter 0
QPDF xref /Index is null 0
@ -332,7 +330,8 @@ QPDFFormFieldObjectHelper TU present 0
QPDFFormFieldObjectHelper TM present 0
QPDFFormFieldObjectHelper TU absent 0
QPDFFormFieldObjectHelper TM absent 0
QPDFFormFieldObjectHelper Q present 1
QPDFFormFieldObjectHelper Q present 0
QPDFFormFieldObjectHelper Q present looked 0
QPDFFormFieldObjectHelper DA present 1
QPDFAnnotationObjectHelper AS present 0
QPDFAnnotationObjectHelper AS absent 0