Commit 5aa8225f493dc3c3171662fecc8a9ff5d0a16feb
Committed by
Jay Berkenbilt
1 parent
0c7c7e4b
Refactor QPDFObjectTypeAccessor and QPDFObjectHandle::dereference
Showing
2 changed files
with
56 additions
and
112 deletions
include/qpdf/QPDFObjectHandle.hh
| @@ -1464,7 +1464,10 @@ class QPDFObjectHandle | @@ -1464,7 +1464,10 @@ class QPDFObjectHandle | ||
| 1464 | static std::shared_ptr<QPDFObject> | 1464 | static std::shared_ptr<QPDFObject> |
| 1465 | getObject(QPDFObjectHandle& o) | 1465 | getObject(QPDFObjectHandle& o) |
| 1466 | { | 1466 | { |
| 1467 | - o.dereference(); | 1467 | + if (!o.dereference()) { |
| 1468 | + throw std::logic_error("attempted to dereference an" | ||
| 1469 | + " uninitialized QPDFObjectHandle"); | ||
| 1470 | + }; | ||
| 1468 | return o.obj; | 1471 | return o.obj; |
| 1469 | } | 1472 | } |
| 1470 | }; | 1473 | }; |
| @@ -1573,7 +1576,7 @@ class QPDFObjectHandle | @@ -1573,7 +1576,7 @@ class QPDFObjectHandle | ||
| 1573 | void typeWarning(char const* expected_type, std::string const& warning); | 1576 | void typeWarning(char const* expected_type, std::string const& warning); |
| 1574 | void objectWarning(std::string const& warning); | 1577 | void objectWarning(std::string const& warning); |
| 1575 | void assertType(char const* type_name, bool istype); | 1578 | void assertType(char const* type_name, bool istype); |
| 1576 | - void dereference(); | 1579 | + bool dereference(); |
| 1577 | void copyObject( | 1580 | void copyObject( |
| 1578 | std::set<QPDFObjGen>& visited, | 1581 | std::set<QPDFObjGen>& visited, |
| 1579 | bool cross_indirect, | 1582 | bool cross_indirect, |
libqpdf/QPDFObjectHandle.cc
| @@ -284,23 +284,14 @@ QPDFObjectHandle::isInitialized() const | @@ -284,23 +284,14 @@ QPDFObjectHandle::isInitialized() const | ||
| 284 | QPDFObject::object_type_e | 284 | QPDFObject::object_type_e |
| 285 | QPDFObjectHandle::getTypeCode() | 285 | QPDFObjectHandle::getTypeCode() |
| 286 | { | 286 | { |
| 287 | - if (this->initialized) { | ||
| 288 | - dereference(); | ||
| 289 | - return this->obj->getTypeCode(); | ||
| 290 | - } else { | ||
| 291 | - return QPDFObject::ot_uninitialized; | ||
| 292 | - } | 287 | + return dereference() ? |
| 288 | + this->obj->getTypeCode() : QPDFObject::ot_uninitialized; | ||
| 293 | } | 289 | } |
| 294 | 290 | ||
| 295 | char const* | 291 | char const* |
| 296 | QPDFObjectHandle::getTypeName() | 292 | QPDFObjectHandle::getTypeName() |
| 297 | { | 293 | { |
| 298 | - if (this->initialized) { | ||
| 299 | - dereference(); | ||
| 300 | - return this->obj->getTypeName(); | ||
| 301 | - } else { | ||
| 302 | - return "uninitialized"; | ||
| 303 | - } | 294 | + return dereference() ? this->obj->getTypeName() : "uninitialized"; |
| 304 | } | 295 | } |
| 305 | 296 | ||
| 306 | namespace | 297 | namespace |
| @@ -310,14 +301,9 @@ namespace | @@ -310,14 +301,9 @@ namespace | ||
| 310 | { | 301 | { |
| 311 | public: | 302 | public: |
| 312 | static bool | 303 | static bool |
| 313 | - check(QPDFObject* o) | 304 | + check(std::shared_ptr<QPDFObject> const& o) |
| 314 | { | 305 | { |
| 315 | - return (o && dynamic_cast<T*>(o)); | ||
| 316 | - } | ||
| 317 | - static bool | ||
| 318 | - check(QPDFObject const* o) | ||
| 319 | - { | ||
| 320 | - return (o && dynamic_cast<T const*>(o)); | 306 | + return (o && dynamic_cast<T const*>(o.get())); |
| 321 | } | 307 | } |
| 322 | }; | 308 | }; |
| 323 | } // namespace | 309 | } // namespace |
| @@ -325,11 +311,7 @@ namespace | @@ -325,11 +311,7 @@ namespace | ||
| 325 | bool | 311 | bool |
| 326 | QPDFObjectHandle::isBool() | 312 | QPDFObjectHandle::isBool() |
| 327 | { | 313 | { |
| 328 | - if (!this->initialized) { | ||
| 329 | - return false; | ||
| 330 | - } | ||
| 331 | - dereference(); | ||
| 332 | - return QPDFObjectTypeAccessor<QPDF_Bool>::check(obj.get()); | 314 | + return dereference() && QPDFObjectTypeAccessor<QPDF_Bool>::check(obj); |
| 333 | } | 315 | } |
| 334 | 316 | ||
| 335 | bool | 317 | bool |
| @@ -339,37 +321,25 @@ QPDFObjectHandle::isDirectNull() const | @@ -339,37 +321,25 @@ QPDFObjectHandle::isDirectNull() const | ||
| 339 | // objid == 0, so there's nothing to resolve. | 321 | // objid == 0, so there's nothing to resolve. |
| 340 | return ( | 322 | return ( |
| 341 | this->initialized && (getObjectID() == 0) && | 323 | this->initialized && (getObjectID() == 0) && |
| 342 | - QPDFObjectTypeAccessor<QPDF_Null>::check(obj.get())); | 324 | + QPDFObjectTypeAccessor<QPDF_Null>::check(obj)); |
| 343 | } | 325 | } |
| 344 | 326 | ||
| 345 | bool | 327 | bool |
| 346 | QPDFObjectHandle::isNull() | 328 | QPDFObjectHandle::isNull() |
| 347 | { | 329 | { |
| 348 | - if (!this->initialized) { | ||
| 349 | - return false; | ||
| 350 | - } | ||
| 351 | - dereference(); | ||
| 352 | - return QPDFObjectTypeAccessor<QPDF_Null>::check(obj.get()); | 330 | + return dereference() && QPDFObjectTypeAccessor<QPDF_Null>::check(obj); |
| 353 | } | 331 | } |
| 354 | 332 | ||
| 355 | bool | 333 | bool |
| 356 | QPDFObjectHandle::isInteger() | 334 | QPDFObjectHandle::isInteger() |
| 357 | { | 335 | { |
| 358 | - if (!this->initialized) { | ||
| 359 | - return false; | ||
| 360 | - } | ||
| 361 | - dereference(); | ||
| 362 | - return QPDFObjectTypeAccessor<QPDF_Integer>::check(obj.get()); | 336 | + return dereference() && QPDFObjectTypeAccessor<QPDF_Integer>::check(obj); |
| 363 | } | 337 | } |
| 364 | 338 | ||
| 365 | bool | 339 | bool |
| 366 | QPDFObjectHandle::isReal() | 340 | QPDFObjectHandle::isReal() |
| 367 | { | 341 | { |
| 368 | - if (!this->initialized) { | ||
| 369 | - return false; | ||
| 370 | - } | ||
| 371 | - dereference(); | ||
| 372 | - return QPDFObjectTypeAccessor<QPDF_Real>::check(obj.get()); | 342 | + return dereference() && QPDFObjectTypeAccessor<QPDF_Real>::check(obj); |
| 373 | } | 343 | } |
| 374 | 344 | ||
| 375 | bool | 345 | bool |
| @@ -406,91 +376,58 @@ QPDFObjectHandle::getValueAsNumber(double& value) | @@ -406,91 +376,58 @@ QPDFObjectHandle::getValueAsNumber(double& value) | ||
| 406 | bool | 376 | bool |
| 407 | QPDFObjectHandle::isName() | 377 | QPDFObjectHandle::isName() |
| 408 | { | 378 | { |
| 409 | - if (!this->initialized) { | ||
| 410 | - return false; | ||
| 411 | - } | ||
| 412 | - dereference(); | ||
| 413 | - return QPDFObjectTypeAccessor<QPDF_Name>::check(obj.get()); | 379 | + return dereference() && QPDFObjectTypeAccessor<QPDF_Name>::check(obj); |
| 414 | } | 380 | } |
| 415 | 381 | ||
| 416 | bool | 382 | bool |
| 417 | QPDFObjectHandle::isString() | 383 | QPDFObjectHandle::isString() |
| 418 | { | 384 | { |
| 419 | - if (!this->initialized) { | ||
| 420 | - return false; | ||
| 421 | - } | ||
| 422 | - dereference(); | ||
| 423 | - return QPDFObjectTypeAccessor<QPDF_String>::check(obj.get()); | 385 | + return dereference() && QPDFObjectTypeAccessor<QPDF_String>::check(obj); |
| 424 | } | 386 | } |
| 425 | 387 | ||
| 426 | bool | 388 | bool |
| 427 | QPDFObjectHandle::isOperator() | 389 | QPDFObjectHandle::isOperator() |
| 428 | { | 390 | { |
| 429 | - if (!this->initialized) { | ||
| 430 | - return false; | ||
| 431 | - } | ||
| 432 | - dereference(); | ||
| 433 | - return QPDFObjectTypeAccessor<QPDF_Operator>::check(obj.get()); | 391 | + return dereference() && QPDFObjectTypeAccessor<QPDF_Operator>::check(obj); |
| 434 | } | 392 | } |
| 435 | 393 | ||
| 436 | bool | 394 | bool |
| 437 | QPDFObjectHandle::isInlineImage() | 395 | QPDFObjectHandle::isInlineImage() |
| 438 | { | 396 | { |
| 439 | - if (!this->initialized) { | ||
| 440 | - return false; | ||
| 441 | - } | ||
| 442 | - dereference(); | ||
| 443 | - return QPDFObjectTypeAccessor<QPDF_InlineImage>::check(obj.get()); | 397 | + return dereference() && |
| 398 | + QPDFObjectTypeAccessor<QPDF_InlineImage>::check(obj); | ||
| 444 | } | 399 | } |
| 445 | 400 | ||
| 446 | bool | 401 | bool |
| 447 | QPDFObjectHandle::isArray() | 402 | QPDFObjectHandle::isArray() |
| 448 | { | 403 | { |
| 449 | - if (!this->initialized) { | ||
| 450 | - return false; | ||
| 451 | - } | ||
| 452 | - dereference(); | ||
| 453 | - return QPDFObjectTypeAccessor<QPDF_Array>::check(obj.get()); | 404 | + return dereference() && QPDFObjectTypeAccessor<QPDF_Array>::check(obj); |
| 454 | } | 405 | } |
| 455 | 406 | ||
| 456 | bool | 407 | bool |
| 457 | QPDFObjectHandle::isDictionary() | 408 | QPDFObjectHandle::isDictionary() |
| 458 | { | 409 | { |
| 459 | - if (!this->initialized) { | ||
| 460 | - return false; | ||
| 461 | - } | ||
| 462 | - dereference(); | ||
| 463 | - return QPDFObjectTypeAccessor<QPDF_Dictionary>::check(obj.get()); | 410 | + return dereference() && |
| 411 | + QPDFObjectTypeAccessor<QPDF_Dictionary>::check(obj); | ||
| 464 | } | 412 | } |
| 465 | 413 | ||
| 466 | bool | 414 | bool |
| 467 | QPDFObjectHandle::isStream() | 415 | QPDFObjectHandle::isStream() |
| 468 | { | 416 | { |
| 469 | - if (!this->initialized) { | ||
| 470 | - return false; | ||
| 471 | - } | ||
| 472 | - dereference(); | ||
| 473 | - return QPDFObjectTypeAccessor<QPDF_Stream>::check(obj.get()); | 417 | + return dereference() && QPDFObjectTypeAccessor<QPDF_Stream>::check(obj); |
| 474 | } | 418 | } |
| 475 | 419 | ||
| 476 | bool | 420 | bool |
| 477 | QPDFObjectHandle::isReserved() | 421 | QPDFObjectHandle::isReserved() |
| 478 | { | 422 | { |
| 479 | - if (!this->initialized) { | ||
| 480 | - return false; | ||
| 481 | - } | ||
| 482 | // dereference will clear reserved if this has been replaced | 423 | // dereference will clear reserved if this has been replaced |
| 483 | - dereference(); | ||
| 484 | - return this->reserved; | 424 | + return dereference() && this->reserved; |
| 485 | } | 425 | } |
| 486 | 426 | ||
| 487 | bool | 427 | bool |
| 488 | QPDFObjectHandle::isIndirect() | 428 | QPDFObjectHandle::isIndirect() |
| 489 | { | 429 | { |
| 490 | - if (!this->initialized) { | ||
| 491 | - return false; | ||
| 492 | - } | ||
| 493 | - return (getObjectID() != 0); | 430 | + return this->initialized && (getObjectID() != 0); |
| 494 | } | 431 | } |
| 495 | 432 | ||
| 496 | bool | 433 | bool |
| @@ -1748,8 +1685,10 @@ QPDFObjectHandle::unparse() | @@ -1748,8 +1685,10 @@ QPDFObjectHandle::unparse() | ||
| 1748 | std::string | 1685 | std::string |
| 1749 | QPDFObjectHandle::unparseResolved() | 1686 | QPDFObjectHandle::unparseResolved() |
| 1750 | { | 1687 | { |
| 1751 | - dereference(); | ||
| 1752 | - if (this->reserved) { | 1688 | + if (!dereference()) { |
| 1689 | + throw std::logic_error( | ||
| 1690 | + "attempted to dereference an uninitialized QPDFObjectHandle"); | ||
| 1691 | + } else if (this->reserved) { | ||
| 1753 | throw std::logic_error( | 1692 | throw std::logic_error( |
| 1754 | "QPDFObjectHandle: attempting to unparse a reserved object"); | 1693 | "QPDFObjectHandle: attempting to unparse a reserved object"); |
| 1755 | } | 1694 | } |
| @@ -1778,12 +1717,13 @@ QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) | @@ -1778,12 +1717,13 @@ QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) | ||
| 1778 | { | 1717 | { |
| 1779 | if ((!dereference_indirect) && this->isIndirect()) { | 1718 | if ((!dereference_indirect) && this->isIndirect()) { |
| 1780 | return JSON::makeString(unparse()); | 1719 | return JSON::makeString(unparse()); |
| 1720 | + } else if (!dereference()) { | ||
| 1721 | + throw std::logic_error( | ||
| 1722 | + "attempted to dereference an uninitialized QPDFObjectHandle"); | ||
| 1723 | + } else if (this->reserved) { | ||
| 1724 | + throw std::logic_error( | ||
| 1725 | + "QPDFObjectHandle: attempting to unparse a reserved object"); | ||
| 1781 | } else { | 1726 | } else { |
| 1782 | - dereference(); | ||
| 1783 | - if (this->reserved) { | ||
| 1784 | - throw std::logic_error( | ||
| 1785 | - "QPDFObjectHandle: attempting to unparse a reserved object"); | ||
| 1786 | - } | ||
| 1787 | return this->obj->getJSON(json_version); | 1727 | return this->obj->getJSON(json_version); |
| 1788 | } | 1728 | } |
| 1789 | } | 1729 | } |
| @@ -2524,8 +2464,11 @@ QPDFObjectHandle::parseInternal( | @@ -2524,8 +2464,11 @@ QPDFObjectHandle::parseInternal( | ||
| 2524 | qpdf_offset_t | 2464 | qpdf_offset_t |
| 2525 | QPDFObjectHandle::getParsedOffset() | 2465 | QPDFObjectHandle::getParsedOffset() |
| 2526 | { | 2466 | { |
| 2527 | - dereference(); | ||
| 2528 | - return this->obj->getParsedOffset(); | 2467 | + if (dereference()) { |
| 2468 | + return this->obj->getParsedOffset(); | ||
| 2469 | + } else { | ||
| 2470 | + return -1; | ||
| 2471 | + } | ||
| 2529 | } | 2472 | } |
| 2530 | 2473 | ||
| 2531 | void | 2474 | void |
| @@ -2723,6 +2666,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf) | @@ -2723,6 +2666,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf) | ||
| 2723 | QPDFObjectHandle stream_dict = newDictionary(); | 2666 | QPDFObjectHandle stream_dict = newDictionary(); |
| 2724 | QPDFObjectHandle result = qpdf->makeIndirectObject( | 2667 | QPDFObjectHandle result = qpdf->makeIndirectObject( |
| 2725 | QPDFObjectHandle(new QPDF_Stream(qpdf, 0, 0, stream_dict, 0, 0))); | 2668 | QPDFObjectHandle(new QPDF_Stream(qpdf, 0, 0, stream_dict, 0, 0))); |
| 2669 | + // Indirect objects are guaranteed to be initialized | ||
| 2726 | result.dereference(); | 2670 | result.dereference(); |
| 2727 | QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(result.obj.get()); | 2671 | QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(result.obj.get()); |
| 2728 | stream->setObjGen(result.getObjectID(), result.getGeneration()); | 2672 | stream->setObjGen(result.getObjectID(), result.getGeneration()); |
| @@ -2771,21 +2715,15 @@ QPDFObjectHandle::setObjectDescription( | @@ -2771,21 +2715,15 @@ QPDFObjectHandle::setObjectDescription( | ||
| 2771 | { | 2715 | { |
| 2772 | // This is called during parsing on newly created direct objects, | 2716 | // This is called during parsing on newly created direct objects, |
| 2773 | // so we can't call dereference() here. | 2717 | // so we can't call dereference() here. |
| 2774 | - if (isInitialized() && this->obj.get()) { | ||
| 2775 | - this->obj->setDescription(owning_qpdf, object_description); | 2718 | + if (isInitialized() && obj.get()) { |
| 2719 | + obj->setDescription(owning_qpdf, object_description); | ||
| 2776 | } | 2720 | } |
| 2777 | } | 2721 | } |
| 2778 | 2722 | ||
| 2779 | bool | 2723 | bool |
| 2780 | QPDFObjectHandle::hasObjectDescription() | 2724 | QPDFObjectHandle::hasObjectDescription() |
| 2781 | { | 2725 | { |
| 2782 | - if (isInitialized()) { | ||
| 2783 | - dereference(); | ||
| 2784 | - if (this->obj.get()) { | ||
| 2785 | - return this->obj->hasDescription(); | ||
| 2786 | - } | ||
| 2787 | - } | ||
| 2788 | - return false; | 2726 | + return dereference() && obj.get() && obj->hasDescription(); |
| 2789 | } | 2727 | } |
| 2790 | 2728 | ||
| 2791 | QPDFObjectHandle | 2729 | QPDFObjectHandle |
| @@ -2868,7 +2806,6 @@ QPDFObjectHandle::copyObject( | @@ -2868,7 +2806,6 @@ QPDFObjectHandle::copyObject( | ||
| 2868 | " reserved object handle direct"); | 2806 | " reserved object handle direct"); |
| 2869 | } | 2807 | } |
| 2870 | 2808 | ||
| 2871 | - dereference(); | ||
| 2872 | this->qpdf = 0; | 2809 | this->qpdf = 0; |
| 2873 | this->objid = 0; | 2810 | this->objid = 0; |
| 2874 | this->generation = 0; | 2811 | this->generation = 0; |
| @@ -2971,7 +2908,12 @@ QPDFObjectHandle::typeWarning( | @@ -2971,7 +2908,12 @@ QPDFObjectHandle::typeWarning( | ||
| 2971 | { | 2908 | { |
| 2972 | QPDF* context = nullptr; | 2909 | QPDF* context = nullptr; |
| 2973 | std::string description; | 2910 | std::string description; |
| 2974 | - dereference(); | 2911 | + // Type checks above guarantee that the object has been dereferenced. |
| 2912 | + // Nevertheless, dereference throws exceptions in the test suite | ||
| 2913 | + if (!dereference()) { | ||
| 2914 | + throw std::logic_error( | ||
| 2915 | + "attempted to dereference an uninitialized QPDFObjectHandle"); | ||
| 2916 | + } | ||
| 2975 | this->obj->getDescription(context, description); | 2917 | this->obj->getDescription(context, description); |
| 2976 | // Null context handled by warn | 2918 | // Null context handled by warn |
| 2977 | warn( | 2919 | warn( |
| @@ -2991,8 +2933,7 @@ QPDFObjectHandle::warnIfPossible(std::string const& warning) | @@ -2991,8 +2933,7 @@ QPDFObjectHandle::warnIfPossible(std::string const& warning) | ||
| 2991 | { | 2933 | { |
| 2992 | QPDF* context = 0; | 2934 | QPDF* context = 0; |
| 2993 | std::string description; | 2935 | std::string description; |
| 2994 | - dereference(); | ||
| 2995 | - if (this->obj->getDescription(context, description)) { | 2936 | + if (dereference() && obj->getDescription(context, description)) { |
| 2996 | warn(context, QPDFExc(qpdf_e_damaged_pdf, "", description, 0, warning)); | 2937 | warn(context, QPDFExc(qpdf_e_damaged_pdf, "", description, 0, warning)); |
| 2997 | } else { | 2938 | } else { |
| 2998 | *QPDFLogger::defaultLogger()->getError() << warning << "\n"; | 2939 | *QPDFLogger::defaultLogger()->getError() << warning << "\n"; |
| @@ -3004,7 +2945,7 @@ QPDFObjectHandle::objectWarning(std::string const& warning) | @@ -3004,7 +2945,7 @@ QPDFObjectHandle::objectWarning(std::string const& warning) | ||
| 3004 | { | 2945 | { |
| 3005 | QPDF* context = nullptr; | 2946 | QPDF* context = nullptr; |
| 3006 | std::string description; | 2947 | std::string description; |
| 3007 | - dereference(); | 2948 | + // Type checks above guarantee that the object has been dereferenced. |
| 3008 | this->obj->getDescription(context, description); | 2949 | this->obj->getDescription(context, description); |
| 3009 | // Null context handled by warn | 2950 | // Null context handled by warn |
| 3010 | warn(context, QPDFExc(qpdf_e_object, "", description, 0, warning)); | 2951 | warn(context, QPDFExc(qpdf_e_object, "", description, 0, warning)); |
| @@ -3187,12 +3128,11 @@ QPDFObjectHandle::assertPageObject() | @@ -3187,12 +3128,11 @@ QPDFObjectHandle::assertPageObject() | ||
| 3187 | } | 3128 | } |
| 3188 | } | 3129 | } |
| 3189 | 3130 | ||
| 3190 | -void | 3131 | +bool |
| 3191 | QPDFObjectHandle::dereference() | 3132 | QPDFObjectHandle::dereference() |
| 3192 | { | 3133 | { |
| 3193 | if (!this->initialized) { | 3134 | if (!this->initialized) { |
| 3194 | - throw std::logic_error( | ||
| 3195 | - "attempted to dereference an uninitialized QPDFObjectHandle"); | 3135 | + return false; |
| 3196 | } | 3136 | } |
| 3197 | if (this->obj.get() && getObjectID() && | 3137 | if (this->obj.get() && getObjectID() && |
| 3198 | QPDF::Resolver::objectChanged(this->qpdf, getObjGen(), this->obj)) { | 3138 | QPDF::Resolver::objectChanged(this->qpdf, getObjGen(), this->obj)) { |
| @@ -3213,6 +3153,7 @@ QPDFObjectHandle::dereference() | @@ -3213,6 +3153,7 @@ QPDFObjectHandle::dereference() | ||
| 3213 | this->obj = obj; | 3153 | this->obj = obj; |
| 3214 | } | 3154 | } |
| 3215 | } | 3155 | } |
| 3156 | + return true; | ||
| 3216 | } | 3157 | } |
| 3217 | 3158 | ||
| 3218 | void | 3159 | void |