Commit 992b7911ce743a87589e6ddf0fe84de1ee4d9366
1 parent
e14e828c
Limit the number of warnings in json_fuzzer before giving up
Showing
2 changed files
with
12 additions
and
6 deletions
fuzz/json_fuzzer.cc
| @@ -33,6 +33,7 @@ FuzzHelper::doChecks() | @@ -33,6 +33,7 @@ FuzzHelper::doChecks() | ||
| 33 | std::cerr << "runtime_error parsing json: " << e.what() << std::endl; | 33 | std::cerr << "runtime_error parsing json: " << e.what() << std::endl; |
| 34 | } | 34 | } |
| 35 | QPDF q; | 35 | QPDF q; |
| 36 | + q.setMaxWarnings(1000); | ||
| 36 | Buffer buf(const_cast<unsigned char*>(data), size); | 37 | Buffer buf(const_cast<unsigned char*>(data), size); |
| 37 | auto is = std::make_shared<BufferInputSource>("json", &buf); | 38 | auto is = std::make_shared<BufferInputSource>("json", &buf); |
| 38 | q.createFromJSON(is); | 39 | q.createFromJSON(is); |
libqpdf/QPDF_json.cc
| @@ -233,12 +233,13 @@ provide_data(std::shared_ptr<InputSource> is, qpdf_offset_t start, qpdf_offset_t | @@ -233,12 +233,13 @@ provide_data(std::shared_ptr<InputSource> is, qpdf_offset_t start, qpdf_offset_t | ||
| 233 | class QPDF::JSONReactor: public JSON::Reactor | 233 | class QPDF::JSONReactor: public JSON::Reactor |
| 234 | { | 234 | { |
| 235 | public: | 235 | public: |
| 236 | - JSONReactor(QPDF& pdf, std::shared_ptr<InputSource> is, bool must_be_complete) : | 236 | + JSONReactor(QPDF& pdf, std::shared_ptr<InputSource> is, bool must_be_complete, int max_warnings) : |
| 237 | pdf(pdf), | 237 | pdf(pdf), |
| 238 | is(is), | 238 | is(is), |
| 239 | must_be_complete(must_be_complete), | 239 | must_be_complete(must_be_complete), |
| 240 | descr(std::make_shared<QPDFValue::Description>( | 240 | descr(std::make_shared<QPDFValue::Description>( |
| 241 | - QPDFValue::JSON_Descr(std::make_shared<std::string>(is->getName()), ""))) | 241 | + QPDFValue::JSON_Descr(std::make_shared<std::string>(is->getName()), ""))), |
| 242 | + max_warnings(max_warnings) | ||
| 242 | { | 243 | { |
| 243 | for (auto& oc: pdf.m->obj_cache) { | 244 | for (auto& oc: pdf.m->obj_cache) { |
| 244 | if (oc.second.object->getTypeCode() == ::ot_reserved) { | 245 | if (oc.second.object->getTypeCode() == ::ot_reserved) { |
| @@ -291,7 +292,8 @@ class QPDF::JSONReactor: public JSON::Reactor | @@ -291,7 +292,8 @@ class QPDF::JSONReactor: public JSON::Reactor | ||
| 291 | std::shared_ptr<InputSource> is; | 292 | std::shared_ptr<InputSource> is; |
| 292 | bool must_be_complete{true}; | 293 | bool must_be_complete{true}; |
| 293 | std::shared_ptr<QPDFValue::Description> descr; | 294 | std::shared_ptr<QPDFValue::Description> descr; |
| 294 | - bool errors{false}; | 295 | + int errors{0}; |
| 296 | + int max_warnings{0}; | ||
| 295 | bool saw_qpdf{false}; | 297 | bool saw_qpdf{false}; |
| 296 | bool saw_qpdf_meta{false}; | 298 | bool saw_qpdf_meta{false}; |
| 297 | bool saw_objects{false}; | 299 | bool saw_objects{false}; |
| @@ -314,18 +316,21 @@ class QPDF::JSONReactor: public JSON::Reactor | @@ -314,18 +316,21 @@ class QPDF::JSONReactor: public JSON::Reactor | ||
| 314 | void | 316 | void |
| 315 | QPDF::JSONReactor::error(qpdf_offset_t offset, std::string const& msg) | 317 | QPDF::JSONReactor::error(qpdf_offset_t offset, std::string const& msg) |
| 316 | { | 318 | { |
| 317 | - this->errors = true; | 319 | + ++errors; |
| 318 | std::string object = this->cur_object; | 320 | std::string object = this->cur_object; |
| 319 | if (is->getName() != pdf.getFilename()) { | 321 | if (is->getName() != pdf.getFilename()) { |
| 320 | object += " from " + is->getName(); | 322 | object += " from " + is->getName(); |
| 321 | } | 323 | } |
| 322 | this->pdf.warn(qpdf_e_json, object, offset, msg); | 324 | this->pdf.warn(qpdf_e_json, object, offset, msg); |
| 325 | + if (max_warnings > 0 && errors >= max_warnings) { | ||
| 326 | + throw std::runtime_error("errors found in JSON"); | ||
| 327 | + } | ||
| 323 | } | 328 | } |
| 324 | 329 | ||
| 325 | bool | 330 | bool |
| 326 | QPDF::JSONReactor::anyErrors() const | 331 | QPDF::JSONReactor::anyErrors() const |
| 327 | { | 332 | { |
| 328 | - return this->errors; | 333 | + return errors > 0; |
| 329 | } | 334 | } |
| 330 | 335 | ||
| 331 | void | 336 | void |
| @@ -820,7 +825,7 @@ QPDF::updateFromJSON(std::shared_ptr<InputSource> is) | @@ -820,7 +825,7 @@ QPDF::updateFromJSON(std::shared_ptr<InputSource> is) | ||
| 820 | void | 825 | void |
| 821 | QPDF::importJSON(std::shared_ptr<InputSource> is, bool must_be_complete) | 826 | QPDF::importJSON(std::shared_ptr<InputSource> is, bool must_be_complete) |
| 822 | { | 827 | { |
| 823 | - JSONReactor reactor(*this, is, must_be_complete); | 828 | + JSONReactor reactor(*this, is, must_be_complete, m->max_warnings); |
| 824 | try { | 829 | try { |
| 825 | JSON::parse(*is, &reactor); | 830 | JSON::parse(*is, &reactor); |
| 826 | } catch (std::runtime_error& e) { | 831 | } catch (std::runtime_error& e) { |