mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 02:49:00 +00:00
Convert stream filtering errors to warnings
This commit is contained in:
parent
40f00122b8
commit
a4fd4b91c6
@ -1,5 +1,9 @@
|
||||
2017-07-27 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* Recover gracefully from streams that aren't filterable because
|
||||
the filter parameters are invalid in the stream dictionary or the
|
||||
dictionary itself is invalid.
|
||||
|
||||
* Significantly improve recoverability from invalid qpdf objects.
|
||||
Most conditions in basic object parsing that used to cause qpdf to
|
||||
exit are now warnings. There are still many more opportunities for
|
||||
|
@ -526,6 +526,7 @@ class QPDF
|
||||
class Warner
|
||||
{
|
||||
friend class QPDFObjectHandle;
|
||||
friend class QPDF_Stream;
|
||||
private:
|
||||
static void warn(QPDF* qpdf, QPDFExc const& e)
|
||||
{
|
||||
|
@ -235,9 +235,10 @@ QPDF_Stream::filterable(std::vector<std::string>& filters,
|
||||
if (! filters_okay)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_Stream invalid filter");
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, qpdf->getFilename(),
|
||||
"", this->offset,
|
||||
"stream filter type is not name or array");
|
||||
warn(QPDFExc(qpdf_e_damaged_pdf, qpdf->getFilename(),
|
||||
"", this->offset,
|
||||
"stream filter type is not name or array"));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool filterable = true;
|
||||
@ -300,12 +301,16 @@ QPDF_Stream::filterable(std::vector<std::string>& filters,
|
||||
// /Filters was empty has been seen in the wild.
|
||||
if ((filters.size() != 0) && (decode_parms.size() != filters.size()))
|
||||
{
|
||||
// We should just issue a warning and treat this as not
|
||||
// filterable.
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, qpdf->getFilename(),
|
||||
"", this->offset,
|
||||
"stream /DecodeParms length is"
|
||||
" inconsistent with filters");
|
||||
warn(QPDFExc(qpdf_e_damaged_pdf, qpdf->getFilename(),
|
||||
"", this->offset,
|
||||
"stream /DecodeParms length is"
|
||||
" inconsistent with filters"));
|
||||
filterable = false;
|
||||
}
|
||||
|
||||
if (! filterable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < filters.size(); ++i)
|
||||
@ -454,7 +459,9 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool filter,
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_Stream provider length mismatch");
|
||||
throw std::logic_error(
|
||||
// This would be caused by programmer error on the
|
||||
// part of a library user, not by invalid input data.
|
||||
throw std::runtime_error(
|
||||
"stream data provider for " +
|
||||
QUtil::int_to_string(this->objid) + " " +
|
||||
QUtil::int_to_string(this->generation) +
|
||||
@ -542,3 +549,9 @@ QPDF_Stream::replaceDict(QPDFObjectHandle new_dict)
|
||||
this->length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Stream::warn(QPDFExc const& e)
|
||||
{
|
||||
QPDF::Warner::warn(this->qpdf, e);
|
||||
}
|
||||
|
@ -646,6 +646,6 @@ QPDF_ERROR_CODE qpdf_write(qpdf_data qpdf)
|
||||
{
|
||||
QPDF_ERROR_CODE status = QPDF_SUCCESS;
|
||||
status = trap_errors(qpdf, &call_write);
|
||||
QTC::TC("qpdf", "qpdf-c called qpdf_write", status);
|
||||
QTC::TC("qpdf", "qpdf-c called qpdf_write", (status == 0) ? 0 : 1);
|
||||
return status;
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ class QPDF_Stream: public QPDFObject
|
||||
int& predictor, int& columns, bool& early_code_change);
|
||||
bool filterable(std::vector<std::string>& filters,
|
||||
int& predictor, int& columns, bool& early_code_change);
|
||||
void warn(QPDFExc const& e);
|
||||
|
||||
QPDF* qpdf;
|
||||
int objid;
|
||||
|
@ -139,7 +139,7 @@ qpdf-c called qpdf_set_preserve_encryption 0
|
||||
qpdf-c called qpdf_set_r2_encryption_parameters 0
|
||||
qpdf-c called qpdf_set_r3_encryption_parameters 0
|
||||
qpdf-c called qpdf_set_linearization 0
|
||||
qpdf-c called qpdf_write 3
|
||||
qpdf-c called qpdf_write 1
|
||||
qpdf-c called qpdf_allow_accessibility 0
|
||||
qpdf-c called qpdf_allow_extract_all 0
|
||||
qpdf-c called qpdf_allow_print_low_res 0
|
||||
|
@ -787,7 +787,7 @@ my @badfiles = ("not a PDF file", # 1
|
||||
"bad dictionary key", # 36
|
||||
);
|
||||
|
||||
$n_tests += @badfiles + 4;
|
||||
$n_tests += @badfiles + 3;
|
||||
|
||||
# Test 6 contains errors in the free table consistency, but we no
|
||||
# longer have any consistency check for this since it is not important
|
||||
@ -796,7 +796,7 @@ $n_tests += @badfiles + 4;
|
||||
# non-fatal.
|
||||
my %badtest_overrides = (6 => 0, 12 => 0, 13 => 0,
|
||||
14 => 0, 15 => 0, 17 => 0,
|
||||
28 => 0, 31 => 0, 36 => 0);
|
||||
28 => 0, 30 => 0, 31 => 0, 36 => 0);
|
||||
for (my $i = 1; $i <= scalar(@badfiles); ++$i)
|
||||
{
|
||||
my $status = $badtest_overrides{$i};
|
||||
@ -813,14 +813,9 @@ $td->runtest("C API: errors",
|
||||
{$td->FILE => "c-read-errors.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("C API: errors writing",
|
||||
{$td->COMMAND => "qpdf-ctest 2 bad30.pdf '' a.pdf"},
|
||||
{$td->FILE => "c-write-errors.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("C API: errors and warnings writing",
|
||||
$td->runtest("C API: warnings writing",
|
||||
{$td->COMMAND => "qpdf-ctest 2 bad33.pdf '' a.pdf"},
|
||||
{$td->FILE => "c-write-warnings-and-errors.out",
|
||||
{$td->FILE => "c-write-warnings.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("C API: no recovery",
|
||||
@ -840,7 +835,7 @@ $n_tests += @badfiles + 8;
|
||||
# though in some cases it may. Acrobat Reader would not be able to
|
||||
# recover any of these files any better.
|
||||
my %recover_failures = ();
|
||||
for (1, 7, 16, 18..21, 24, 29..30, 33, 35)
|
||||
for (1, 7, 16, 18..21, 24, 29, 35)
|
||||
{
|
||||
$recover_failures{$_} = 1;
|
||||
}
|
||||
|
@ -3,4 +3,8 @@
|
||||
Raw stream data:
|
||||
xœ%<25>11û¼b;t<>à4| wXIDì Øå÷8G·«Í>rQ¨uŠOÒêEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»ž<C2BB>T.?®uŽæ§<Ž¼…Ð*6ä
|
||||
Uncompressed stream data:
|
||||
bad30.pdf (file position 629): stream filter type is not name or array
|
||||
WARNING: bad30.pdf (file position 629): stream filter type is not name or array
|
||||
Stream data is not filterable.
|
||||
unparse: 7 0 R
|
||||
unparseResolved: 7 0 R
|
||||
test 1 done
|
||||
|
@ -3,4 +3,8 @@
|
||||
Raw stream data:
|
||||
xœ%<25>11û¼b;t<>à4| wXIDì Øå÷8G·«Í>rQ¨uŠOÒêEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»ž<C2BB>T.?®uŽæ§<Ž¼…Ð*6ä
|
||||
Uncompressed stream data:
|
||||
bad30.pdf (file position 629): stream filter type is not name or array
|
||||
WARNING: bad30.pdf (file position 629): stream filter type is not name or array
|
||||
Stream data is not filterable.
|
||||
unparse: 7 0 R
|
||||
unparseResolved: 7 0 R
|
||||
test 0 done
|
||||
|
@ -6,4 +6,8 @@ WARNING: bad33.pdf: Attempting to reconstruct cross-reference table
|
||||
Raw stream data:
|
||||
xœ%<25>11û¼b;t<>à4| wXIDì Øå÷8G·«Í>rQ¨uŠOÒêEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»ž<C2BB>T.?®uŽæ§<Ž¼…Ð*6ä
|
||||
Uncompressed stream data:
|
||||
bad33.pdf (file position 629): stream filter type is not name or array
|
||||
WARNING: bad33.pdf (file position 629): stream filter type is not name or array
|
||||
Stream data is not filterable.
|
||||
unparse: 7 0 R
|
||||
unparseResolved: 7 0 R
|
||||
test 1 done
|
||||
|
@ -1,5 +0,0 @@
|
||||
error: bad30.pdf (file position 629): stream filter type is not name or array
|
||||
code: 5
|
||||
file: bad30.pdf
|
||||
pos : 629
|
||||
text: stream filter type is not name or array
|
@ -13,7 +13,12 @@ warning: bad33.pdf: Attempting to reconstruct cross-reference table
|
||||
file: bad33.pdf
|
||||
pos : 0
|
||||
text: Attempting to reconstruct cross-reference table
|
||||
error: bad33.pdf (file position 629): stream filter type is not name or array
|
||||
warning: bad33.pdf (file position 629): stream filter type is not name or array
|
||||
code: 5
|
||||
file: bad33.pdf
|
||||
pos : 629
|
||||
text: stream filter type is not name or array
|
||||
warning: bad33.pdf (file position 629): stream filter type is not name or array
|
||||
code: 5
|
||||
file: bad33.pdf
|
||||
pos : 629
|
@ -567,7 +567,7 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
qstream.getStreamData();
|
||||
std::cout << "oops -- getStreamData didn't throw" << std::endl;
|
||||
}
|
||||
catch (std::logic_error const& e)
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
std::cout << "exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user