From 8318d81ada86d4ec8e343c47103932b6bbe45a42 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 24 Jun 2012 15:26:28 -0400 Subject: Fix and test support for files >= 4 GB --- libqpdf/BitStream.cc | 2 +- libqpdf/BitWriter.cc | 2 +- libqpdf/QPDF.cc | 20 +++++++++++++------- libqpdf/QPDFWriter.cc | 35 ++++++++++++++++++----------------- libqpdf/QPDF_linearization.cc | 24 ++++++++++++------------ libqpdf/bits.icc | 4 ++-- libqpdf/qpdf-c.cc | 6 +++--- libqpdf/qpdf/BitStream.hh | 2 +- libqpdf/qpdf/BitWriter.hh | 2 +- 9 files changed, 52 insertions(+), 45 deletions(-) (limited to 'libqpdf') diff --git a/libqpdf/BitStream.cc b/libqpdf/BitStream.cc index 703ce8f2..eb511f72 100644 --- a/libqpdf/BitStream.cc +++ b/libqpdf/BitStream.cc @@ -19,7 +19,7 @@ BitStream::reset() bits_available = 8 * nbytes; } -unsigned long +unsigned long long BitStream::getBits(int nbits) { return read_bits(this->p, this->bit_offset, diff --git a/libqpdf/BitWriter.cc b/libqpdf/BitWriter.cc index 441501cb..4fb375cb 100644 --- a/libqpdf/BitWriter.cc +++ b/libqpdf/BitWriter.cc @@ -12,7 +12,7 @@ BitWriter::BitWriter(Pipeline* pl) : } void -BitWriter::writeBits(unsigned long val, unsigned int bits) +BitWriter::writeBits(unsigned long long val, unsigned int bits) { write_bits(this->ch, this->bit_offset, val, bits, this->pl); } diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 6b275d28..743ba93b 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -571,7 +571,7 @@ QPDF::reconstruct_xref(QPDFExc& e) in_obj = true; int obj = atoi(m.getMatch(1).c_str()); int gen = atoi(m.getMatch(2).c_str()); - int offset = this->file->getLastOffset(); + qpdf_offset_t offset = this->file->getLastOffset(); insertXrefEntry(obj, 1, offset, gen, true); } else if ((! this->trailer.isInitialized()) && @@ -634,6 +634,11 @@ QPDF::read_xref(qpdf_offset_t xref_offset) } } + if (! this->trailer.isInitialized()) + { + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0, + "unable to find trailer while reading xref"); + } int size = this->trailer.getKey("/Size").getIntValue(); int max_obj = 0; if (! xref_table.empty()) @@ -704,7 +709,8 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) QUtil::int_to_string(i) + ")"); } - int f1 = atoi(m2.getMatch(1).c_str()); + // 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]; if (type == 'f') @@ -855,7 +861,7 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset) return xref_offset; } -int +qpdf_offset_t QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) { QPDFObjectHandle dict = xref_obj.getDict(); @@ -957,7 +963,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) { // Read this entry unsigned char const* entry = data + (entry_size * i); - int fields[3]; + qpdf_offset_t fields[3]; unsigned char const* p = entry; for (int j = 0; j < 3; ++j) { @@ -1002,7 +1008,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) // This is needed by checkLinearization() this->first_xref_item_offset = xref_offset; } - insertXrefEntry(obj, fields[0], fields[1], fields[2]); + insertXrefEntry(obj, (int)fields[0], fields[1], (int)fields[2]); } if (! this->trailer.isInitialized()) @@ -1031,7 +1037,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) } void -QPDF::insertXrefEntry(int obj, int f0, int f1, int f2, bool overwrite) +QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite) { // Populate the xref table in such a way that the first reference // to an object that we see, which is the one in the latest xref @@ -1558,7 +1564,7 @@ QPDF::recoverStreamLength(PointerHolder input, QPDFXRefEntry const& entry = (*iter).second; if (entry.getType() == 1) { - int obj_offset = entry.getOffset(); + qpdf_offset_t obj_offset = entry.getOffset(); if ((obj_offset > stream_offset) && ((this_obj_offset == 0) || (this_obj_offset > obj_offset))) diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 308f4c53..26713225 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -540,7 +540,7 @@ QPDFWriter::setDataKey(int objid) } int -QPDFWriter::bytesNeeded(unsigned long n) +QPDFWriter::bytesNeeded(unsigned long long n) { int bytes = 0; while (n) @@ -552,10 +552,10 @@ QPDFWriter::bytesNeeded(unsigned long n) } void -QPDFWriter::writeBinary(unsigned long val, unsigned int bytes) +QPDFWriter::writeBinary(unsigned long long val, unsigned int bytes) { - assert(bytes <= sizeof(unsigned long)); - unsigned char data[sizeof(unsigned long)]; + assert(bytes <= sizeof(unsigned long long)); + unsigned char data[sizeof(unsigned long long)]; for (unsigned int i = 0; i < bytes; ++i) { data[bytes - i - 1] = (unsigned char)(val & 0xff); @@ -849,7 +849,8 @@ QPDFWriter::unparseChild(QPDFObjectHandle child, int level, int flags) } void -QPDFWriter::writeTrailer(trailer_e which, int size, bool xref_stream, int prev) +QPDFWriter::writeTrailer(trailer_e which, int size, bool xref_stream, + qpdf_offset_t prev) { QPDFObjectHandle trailer = pdf.getTrailer(); if (! xref_stream) @@ -1812,15 +1813,15 @@ QPDFWriter::writeHintStream(int hint_id) closeObject(hint_id); } -int +qpdf_offset_t QPDFWriter::writeXRefTable(trailer_e which, int first, int last, int size) { return writeXRefTable(which, first, last, size, 0, false, 0, 0, 0); } -int +qpdf_offset_t QPDFWriter::writeXRefTable(trailer_e which, int first, int last, int size, - int prev, bool suppress_offsets, + qpdf_offset_t prev, bool suppress_offsets, int hint_id, qpdf_offset_t hint_offset, qpdf_offset_t hint_length) { @@ -1838,7 +1839,7 @@ QPDFWriter::writeXRefTable(trailer_e which, int first, int last, int size, } else { - int offset = 0; + qpdf_offset_t offset = 0; if (! suppress_offsets) { offset = this->xref[i].getOffset(); @@ -1858,24 +1859,24 @@ QPDFWriter::writeXRefTable(trailer_e which, int first, int last, int size, return space_before_zero; } -int -QPDFWriter::writeXRefStream(int objid, int max_id, int max_offset, +qpdf_offset_t +QPDFWriter::writeXRefStream(int objid, int max_id, qpdf_offset_t max_offset, trailer_e which, int first, int last, int size) { return writeXRefStream(objid, max_id, max_offset, which, first, last, size, 0, 0, 0, 0, false); } -int -QPDFWriter::writeXRefStream(int xref_id, int max_id, int max_offset, +qpdf_offset_t +QPDFWriter::writeXRefStream(int xref_id, int max_id, qpdf_offset_t max_offset, trailer_e which, int first, int last, int size, - int prev, int hint_id, + qpdf_offset_t prev, int hint_id, qpdf_offset_t hint_offset, qpdf_offset_t hint_length, bool skip_compression) { qpdf_offset_t xref_offset = this->pipeline->getCount(); - int space_before_zero = xref_offset - 1; + qpdf_offset_t space_before_zero = xref_offset - 1; // field 1 contains offsets and object stream identifiers int f1_size = std::max(bytesNeeded(max_offset), @@ -1921,7 +1922,7 @@ QPDFWriter::writeXRefStream(int xref_id, int max_id, int max_offset, case 1: { - int offset = e.getOffset(); + qpdf_offset_t offset = e.getOffset(); if ((hint_id != 0) && (i != hint_id) && (offset >= hint_offset)) @@ -2309,7 +2310,7 @@ QPDFWriter::writeLinearized() // Save hint offset since it will be set to zero by // calling openObject. - int hint_offset = this->xref[hint_id].getOffset(); + qpdf_offset_t hint_offset = this->xref[hint_id].getOffset(); // Write hint stream to a buffer pushPipeline(new Pl_Buffer("hint buffer")); diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index 48bb4d2b..fdd0d702 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -18,10 +18,10 @@ #include #include -template +template static void load_vector_int(BitStream& bit_stream, int nitems, std::vector& vec, - int bits_wanted, int T::*field) + int bits_wanted, int_type T::*field) { // nitems times, read bits_wanted from the given bit stream, // storing results in the ith vector entry. @@ -144,7 +144,7 @@ QPDF::isLinearized() QPDFObjectHandle L = candidate.getKey("/L"); if (L.isInteger()) { - int Li = L.getIntValue(); + qpdf_offset_t Li = L.getIntValue(); this->file->seek(0, SEEK_END); if (Li != this->file->tell()) { @@ -649,11 +649,11 @@ QPDF::maxEnd(ObjUser const& ou) return end; } -int +qpdf_offset_t QPDF::getLinearizationOffset(ObjGen const& og) { QPDFXRefEntry entry = this->xref_table[og]; - int result = 0; + qpdf_offset_t result = 0; switch (entry.getType()) { case 1: @@ -1787,7 +1787,7 @@ static inline int nbits(int val) int QPDF::outputLengthNextN( int in_object, int n, - std::map const& lengths, + std::map const& lengths, std::map const& obj_renumber) { // Figure out the length of a series of n consecutive objects in @@ -1808,7 +1808,7 @@ QPDF::outputLengthNextN( void QPDF::calculateHPageOffset( std::map const& xref, - std::map const& lengths, + std::map const& lengths, std::map const& obj_renumber) { // Page Offset Hint Table @@ -1900,7 +1900,7 @@ QPDF::calculateHPageOffset( void QPDF::calculateHSharedObject( std::map const& xref, - std::map const& lengths, + std::map const& lengths, std::map const& obj_renumber) { CHSharedObject& cso = this->c_shared_object_data; @@ -1946,7 +1946,7 @@ QPDF::calculateHSharedObject( void QPDF::calculateHOutline( std::map const& xref, - std::map const& lengths, + std::map const& lengths, std::map const& obj_renumber) { HGeneric& cho = this->c_outline_data; @@ -1967,10 +1967,10 @@ QPDF::calculateHOutline( cho.first_object, ho.nobjects, lengths, obj_renumber); } -template +template static void write_vector_int(BitWriter& w, int nitems, std::vector& vec, - int bits, int T::*field) + int bits, int_type T::*field) { // nitems times, write bits bits from the given field of the ith // vector to the given bit writer. @@ -2095,7 +2095,7 @@ QPDF::writeHGeneric(BitWriter& w, HGeneric& t) void QPDF::generateHintStream(std::map const& xref, - std::map const& lengths, + std::map const& lengths, std::map const& obj_renumber, PointerHolder& hint_buffer, int& S, int& O) diff --git a/libqpdf/bits.icc b/libqpdf/bits.icc index 31765986..bcd7dd85 100644 --- a/libqpdf/bits.icc +++ b/libqpdf/bits.icc @@ -15,7 +15,7 @@ // this code includes with the symbol defined. #ifdef BITS_READ -static unsigned long +static unsigned long long read_bits(unsigned char const*& p, unsigned int& bit_offset, unsigned int& bits_available, unsigned int bits_wanted) { @@ -95,7 +95,7 @@ read_bits(unsigned char const*& p, unsigned int& bit_offset, #ifdef BITS_WRITE static void write_bits(unsigned char& ch, unsigned int& bit_offset, - unsigned long val, unsigned int bits, Pipeline* pipeline) + unsigned long long val, unsigned int bits, Pipeline* pipeline) { if (bits > 32) { diff --git a/libqpdf/qpdf-c.cc b/libqpdf/qpdf-c.cc index 65a5de72..0312ae50 100644 --- a/libqpdf/qpdf-c.cc +++ b/libqpdf/qpdf-c.cc @@ -31,7 +31,7 @@ struct _qpdf_data // Parameters for functions we call char const* filename; // or description char const* buffer; - unsigned long size; + unsigned long long size; char const* password; bool write_memory; Buffer* output_buffer; @@ -218,7 +218,7 @@ char const* qpdf_get_error_filename(qpdf_data qpdf, qpdf_error e) return e->exc->getFilename().c_str(); } -unsigned long qpdf_get_error_file_position(qpdf_data qpdf, qpdf_error e) +unsigned long long qpdf_get_error_file_position(qpdf_data qpdf, qpdf_error e) { if (e == 0) { @@ -268,7 +268,7 @@ QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename, QPDF_ERROR_CODE qpdf_read_memory(qpdf_data qpdf, char const* description, char const* buffer, - unsigned long size, + unsigned long long size, char const* password) { QPDF_ERROR_CODE status = QPDF_SUCCESS; diff --git a/libqpdf/qpdf/BitStream.hh b/libqpdf/qpdf/BitStream.hh index 92bbd735..e45a90ee 100644 --- a/libqpdf/qpdf/BitStream.hh +++ b/libqpdf/qpdf/BitStream.hh @@ -13,7 +13,7 @@ class BitStream QPDF_DLL void reset(); QPDF_DLL - unsigned long getBits(int nbits); + unsigned long long getBits(int nbits); QPDF_DLL void skipToNextByte(); diff --git a/libqpdf/qpdf/BitWriter.hh b/libqpdf/qpdf/BitWriter.hh index 5eae398f..7e3b07a9 100644 --- a/libqpdf/qpdf/BitWriter.hh +++ b/libqpdf/qpdf/BitWriter.hh @@ -15,7 +15,7 @@ class BitWriter QPDF_DLL BitWriter(Pipeline* pl); QPDF_DLL - void writeBits(unsigned long val, unsigned int bits); + void writeBits(unsigned long long val, unsigned int bits); // Force any partial byte to be written to the pipeline. QPDF_DLL void flush(); -- cgit v1.2.3-70-g09d2