2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 19:08:59 +00:00

Change QPDF max_warnings into a hard limit

Throw damagedFile if max_warnings is exceeded. Change qpdf_fuzzer warnings limit to
limit to 500.
This commit is contained in:
m-holger 2024-07-18 10:41:15 +01:00
parent bcf81a1423
commit fe1fffe8db
4 changed files with 15 additions and 22 deletions

View File

@ -57,7 +57,7 @@ FuzzHelper::getQpdf()
auto is = auto is =
std::shared_ptr<InputSource>(new BufferInputSource("fuzz input", &this->input_buffer)); std::shared_ptr<InputSource>(new BufferInputSource("fuzz input", &this->input_buffer));
auto qpdf = QPDF::create(); auto qpdf = QPDF::create();
qpdf->setMaxWarnings(20); qpdf->setMaxWarnings(500);
qpdf->processInputSource(is); qpdf->processInputSource(is);
return qpdf; return qpdf;
} }

View File

@ -228,9 +228,9 @@ class QPDF
QPDF_DLL QPDF_DLL
void setSuppressWarnings(bool); void setSuppressWarnings(bool);
// Set the maximum number of warnings to output. Subsequent warnings are suppressed. // Set the maximum number of warnings. A QPDFExc is thrown if the limit is exceeded.
QPDF_DLL QPDF_DLL
void setMaxWarnings(int); void setMaxWarnings(size_t);
// By default, QPDF will try to recover if it finds certain types of errors in PDF files. If // By default, QPDF will try to recover if it finds certain types of errors in PDF files. If
// turned off, it will throw an exception on the first such problem it finds without attempting // turned off, it will throw an exception on the first such problem it finds without attempting
@ -1501,7 +1501,7 @@ class QPDF
bool provided_password_is_hex_key{false}; bool provided_password_is_hex_key{false};
bool ignore_xref_streams{false}; bool ignore_xref_streams{false};
bool suppress_warnings{false}; bool suppress_warnings{false};
int max_warnings{0}; size_t max_warnings{0};
bool attempt_recovery{true}; bool attempt_recovery{true};
bool check_mode{false}; bool check_mode{false};
std::shared_ptr<EncryptionParameters> encp; std::shared_ptr<EncryptionParameters> encp;

View File

@ -332,7 +332,7 @@ QPDF::setSuppressWarnings(bool val)
} }
void void
QPDF::setMaxWarnings(int val) QPDF::setMaxWarnings(size_t val)
{ {
m->max_warnings = val; m->max_warnings = val;
} }
@ -504,13 +504,11 @@ QPDF::inParse(bool v)
void void
QPDF::warn(QPDFExc const& e) QPDF::warn(QPDFExc const& e)
{ {
if (m->max_warnings > 0 && m->warnings.size() >= m->max_warnings) {
stopOnError("Too many warnings - file is too badly damaged");
}
m->warnings.push_back(e); m->warnings.push_back(e);
if (!m->suppress_warnings) { if (!m->suppress_warnings) {
if (m->max_warnings > 0 && m->warnings.size() > 20) {
*m->log->getWarn() << "WARNING: too many warnings - additional warnings suppressed\n";
m->suppress_warnings = true;
return;
}
*m->log->getWarn() << "WARNING: " << m->warnings.back().what() << "\n"; *m->log->getWarn() << "WARNING: " << m->warnings.back().what() << "\n";
} }
} }

View File

@ -233,13 +233,12 @@ provide_data(std::shared_ptr<InputSource> is, qpdf_offset_t start, qpdf_offset_t
class QPDF::JSONReactor: public JSON::Reactor class QPDF::JSONReactor: public JSON::Reactor
{ {
public: public:
JSONReactor(QPDF& pdf, std::shared_ptr<InputSource> is, bool must_be_complete, int max_warnings) : JSONReactor(QPDF& pdf, std::shared_ptr<InputSource> is, bool must_be_complete) :
pdf(pdf), pdf(pdf),
is(is), is(is),
must_be_complete(must_be_complete), must_be_complete(must_be_complete),
descr(std::make_shared<QPDFValue::Description>( descr(std::make_shared<QPDFValue::Description>(
QPDFValue::JSON_Descr(std::make_shared<std::string>(is->getName()), ""))), QPDFValue::JSON_Descr(std::make_shared<std::string>(is->getName()), "")))
max_warnings(max_warnings)
{ {
for (auto& oc: pdf.m->obj_cache) { for (auto& oc: pdf.m->obj_cache) {
if (oc.second.object->getTypeCode() == ::ot_reserved) { if (oc.second.object->getTypeCode() == ::ot_reserved) {
@ -292,8 +291,7 @@ class QPDF::JSONReactor: public JSON::Reactor
std::shared_ptr<InputSource> is; std::shared_ptr<InputSource> is;
bool must_be_complete{true}; bool must_be_complete{true};
std::shared_ptr<QPDFValue::Description> descr; std::shared_ptr<QPDFValue::Description> descr;
int errors{0}; bool errors{false};
int max_warnings{0};
bool saw_qpdf{false}; bool saw_qpdf{false};
bool saw_qpdf_meta{false}; bool saw_qpdf_meta{false};
bool saw_objects{false}; bool saw_objects{false};
@ -316,21 +314,18 @@ class QPDF::JSONReactor: public JSON::Reactor
void void
QPDF::JSONReactor::error(qpdf_offset_t offset, std::string const& msg) QPDF::JSONReactor::error(qpdf_offset_t offset, std::string const& msg)
{ {
++errors; errors = true;
std::string object = this->cur_object; std::string object = this->cur_object;
if (is->getName() != pdf.getFilename()) { if (is->getName() != pdf.getFilename()) {
object += " from " + is->getName(); object += " from " + is->getName();
} }
this->pdf.warn(qpdf_e_json, object, offset, msg); pdf.warn(qpdf_e_json, object, offset, msg);
if (max_warnings > 0 && errors >= max_warnings) {
throw std::runtime_error("errors found in JSON");
}
} }
bool bool
QPDF::JSONReactor::anyErrors() const QPDF::JSONReactor::anyErrors() const
{ {
return errors > 0; return errors;
} }
void void
@ -825,7 +820,7 @@ QPDF::updateFromJSON(std::shared_ptr<InputSource> is)
void void
QPDF::importJSON(std::shared_ptr<InputSource> is, bool must_be_complete) QPDF::importJSON(std::shared_ptr<InputSource> is, bool must_be_complete)
{ {
JSONReactor reactor(*this, is, must_be_complete, m->max_warnings); JSONReactor reactor(*this, is, must_be_complete);
try { try {
JSON::parse(*is, &reactor); JSON::parse(*is, &reactor);
} catch (std::runtime_error& e) { } catch (std::runtime_error& e) {