Commit 4630b8567c853e0a05d41f15b701c370f660250f

Authored by m-holger
1 parent ce7db05d

Ensure qpdf_oh handles returned by C-API functions are unique.

Return new qpdf_oh from qpdf_oh_wrap_in_array when input is already an array.
Update some doc comments in qpdf-c.h.
include/qpdf/qpdf-c.h
@@ -134,7 +134,7 @@ extern "C" { @@ -134,7 +134,7 @@ extern "C" {
134 134
135 /* Returns the error condition, if any. The return value is a 135 /* Returns the error condition, if any. The return value is a
136 * pointer to data that will become invalid after the next call to 136 * pointer to data that will become invalid after the next call to
137 - * this function, qpdf_next_warning, or qpdf_destroy. After this 137 + * this function, qpdf_next_warning, or qpdf_cleanup. After this
138 * function is called, qpdf_has_error will return QPDF_FALSE until 138 * function is called, qpdf_has_error will return QPDF_FALSE until
139 * the next error condition occurs. If there is no error 139 * the next error condition occurs. If there is no error
140 * condition, this function returns a null pointer. 140 * condition, this function returns a null pointer.
@@ -201,7 +201,7 @@ extern "C" { @@ -201,7 +201,7 @@ extern "C" {
201 /* Calling qpdf_read causes processFile to be called in the C++ 201 /* Calling qpdf_read causes processFile to be called in the C++
202 * API. Basic parsing is performed, but data from the file is 202 * API. Basic parsing is performed, but data from the file is
203 * only read as needed. For files without passwords, pass a null 203 * only read as needed. For files without passwords, pass a null
204 - * pointer as the password. 204 + * pointer or an empty string as the password.
205 */ 205 */
206 QPDF_DLL 206 QPDF_DLL
207 QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename, 207 QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename,
@@ -489,16 +489,19 @@ extern "C" { @@ -489,16 +489,19 @@ extern "C" {
489 489
490 /* Object handling. 490 /* Object handling.
491 * 491 *
492 - * These methods take and return a qpdf_oh, which is just an  
493 - * unsigned integer. The value 0 is never returned, which makes it  
494 - * usable as an uninitialized value. 492 + * These functions take and return a qpdf_oh object handle, which
  493 + * is just an unsigned integer. The value 0 is never returned, which
  494 + * makes it usable as an uninitialized value. The handles returned by
  495 + * these functions are guaranteed to be unique, i.e. two calls to
  496 + * (the same of different) functions will return distinct handles
  497 + * even when they refer to the same object.
495 * 498 *
496 * Each function below, starting with qpdf_oh, corresponds to a 499 * Each function below, starting with qpdf_oh, corresponds to a
497 * specific method of QPDFObjectHandler. For example, 500 * specific method of QPDFObjectHandler. For example,
498 * qpdf_oh_is_bool corresponds to QPDFObjectHandle::isBool. If the 501 * qpdf_oh_is_bool corresponds to QPDFObjectHandle::isBool. If the
499 * C++ method is overloaded, the C function's name will be 502 * C++ method is overloaded, the C function's name will be
500 * disambiguated. If the C++ method takes optional argumens, the C 503 * disambiguated. If the C++ method takes optional argumens, the C
501 - * method will have required arguments in those positions. For 504 + * function will have required arguments in those positions. For
502 * details about the method, please see comments in 505 * details about the method, please see comments in
503 * QPDFObjectHandle.hh. Comments here only explain things that are 506 * QPDFObjectHandle.hh. Comments here only explain things that are
504 * specific to the "C" API. 507 * specific to the "C" API.
@@ -514,25 +517,26 @@ extern "C" { @@ -514,25 +517,26 @@ extern "C" {
514 * To refer to a specific QPDFObjectHandle, you need a pair 517 * To refer to a specific QPDFObjectHandle, you need a pair
515 * consisting of a qpdf_data and a qpdf_oh, which is just an index 518 * consisting of a qpdf_data and a qpdf_oh, which is just an index
516 * into an internal table of objects. All memory allocated by any 519 * into an internal table of objects. All memory allocated by any
517 - * of these methods is returned when qpdf_cleanup is called. 520 + * of these functions is returned when qpdf_cleanup is called.
518 * 521 *
519 * Regarding memory, the same rules apply as the above functions. 522 * Regarding memory, the same rules apply as the above functions.
520 - * Specifically, if a method returns a char*, the memory is 523 + * Specifically, if a function returns a char*, the memory is
521 * managed by the library and, unless otherwise specified, is not 524 * managed by the library and, unless otherwise specified, is not
522 * expected to be valid after the next qpdf call. 525 * expected to be valid after the next qpdf call.
523 * 526 *
524 - * The qpdf_data object keeps a cache of objects returned by these  
525 - * methods. Once you are finished referencing an object, you can  
526 - * optionally release it. Releasing objects is optional since they 527 + * The qpdf_data object keeps a cache of handles returned by these
  528 + * functions. Once you are finished referencing an handle, you can
  529 + * optionally release it. Releasing handles is optional since they
527 * will all get released by qpdf_cleanup, but it can help to 530 * will all get released by qpdf_cleanup, but it can help to
528 * reduce the memory footprint of the qpdf_data object to release 531 * reduce the memory footprint of the qpdf_data object to release
529 - * them when you're done. Releasing an object does not destroy the 532 + * them when you're done. Releasing a handle does not destroy the
530 * object. All QPDFObjectHandle objects are deleted when they are 533 * object. All QPDFObjectHandle objects are deleted when they are
531 - * no longer referenced. Releasing an object simply invalidates  
532 - * the qpdf_oh handle to it. For example, if you create an object,  
533 - * add it to an existing dictionary or array, and then release it,  
534 - * the object is safely part of the dictionary or array.  
535 - * Explicitly releasing an object is essentially the same as 534 + * no longer referenced. Releasing an object handle simply
  535 + * invalidates it. For example, if you create an object,
  536 + * add it to an existing dictionary or array, and then release it's
  537 + * handle, the object is safely part of the dictionary or array.
  538 + * Similarly, any other object handle refering to the object remains
  539 + * valid. Explicitly releasing an object is essentially the same as
536 * letting a QPDFObjectHandle go out of scope in the C++ API. 540 * letting a QPDFObjectHandle go out of scope in the C++ API.
537 */ 541 */
538 542
@@ -540,7 +544,7 @@ extern "C" { @@ -540,7 +544,7 @@ extern "C" {
540 544
541 typedef unsigned int qpdf_oh; 545 typedef unsigned int qpdf_oh;
542 546
543 - /* Releasing objects -- see comments above. These methods have no 547 + /* Releasing objects -- see comments above. These functions have no
544 * equivalent in the C++ API. 548 * equivalent in the C++ API.
545 */ 549 */
546 QPDF_DLL 550 QPDF_DLL
libqpdf/qpdf-c.cc
@@ -987,7 +987,7 @@ qpdf_oh qpdf_oh_wrap_in_array(qpdf_data qpdf, qpdf_oh oh) @@ -987,7 +987,7 @@ qpdf_oh qpdf_oh_wrap_in_array(qpdf_data qpdf, qpdf_oh oh)
987 if (qoh->isArray()) 987 if (qoh->isArray())
988 { 988 {
989 QTC::TC("qpdf", "qpdf-c array to wrap_in_array"); 989 QTC::TC("qpdf", "qpdf-c array to wrap_in_array");
990 - return oh; 990 + return new_object(qpdf, *qoh);
991 } 991 }
992 else 992 else
993 { 993 {
qpdf/qpdf-ctest.c
@@ -530,7 +530,9 @@ static void test24(char const* infile, @@ -530,7 +530,9 @@ static void test24(char const* infile,
530 assert(! qpdf_oh_is_scalar(qpdf, mediabox)); 530 assert(! qpdf_oh_is_scalar(qpdf, mediabox));
531 assert(qpdf_oh_is_array(qpdf, mediabox)); 531 assert(qpdf_oh_is_array(qpdf, mediabox));
532 assert(qpdf_oh_get_array_n_items(qpdf, mediabox) == 4); 532 assert(qpdf_oh_get_array_n_items(qpdf, mediabox) == 4);
533 - assert(qpdf_oh_wrap_in_array(qpdf, mediabox) == mediabox); 533 + qpdf_oh wrapped_mediabox = qpdf_oh_wrap_in_array(qpdf, mediabox);
  534 + assert(wrapped_mediabox != mediabox);
  535 + assert(qpdf_oh_get_array_n_items(qpdf, wrapped_mediabox) == 4);
534 for (int i = 0; i < 4; ++i) 536 for (int i = 0; i < 4; ++i)
535 { 537 {
536 qpdf_oh item = qpdf_oh_get_array_item(qpdf, mediabox, i); 538 qpdf_oh item = qpdf_oh_get_array_item(qpdf, mediabox, i);