diff --git a/ChangeLog b/ChangeLog index 3b646ee..978c1bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2024-09-20 Chao Li + + * Add C API qpdf_oh_free_buffer to release memory allocated by + stream data functions. + 2024-08-25 M Holger * Add new command-line arguments --remove-metadata and --remove-info diff --git a/include/qpdf/qpdf-c.h b/include/qpdf/qpdf-c.h index fba952f..b295d52 100644 --- a/include/qpdf/qpdf-c.h +++ b/include/qpdf/qpdf-c.h @@ -927,6 +927,14 @@ extern "C" { QPDF_ERROR_CODE qpdf_oh_get_page_content_data( qpdf_data qpdf, qpdf_oh page_oh, unsigned char** bufp, size_t* len); + /* Call free to release the buffer allocated with malloc. This function can be used to free + * buffers that were dynamically allocated by qpdf functions such as qpdf_oh_get_stream_data + * or qpdf_oh_get_page_content_data. The caller is responsible for calling qpdf_oh_free_buffer + * to manage memory properly and avoid memory leaks. + */ + QPDF_DLL + void qpdf_oh_free_buffer(unsigned char** bufp); + /* The data pointed to by bufp will be copied by the library. It does not need to remain valid * after the call returns. */ diff --git a/libqpdf/qpdf-c.cc b/libqpdf/qpdf-c.cc index e2b9d82..a491218 100644 --- a/libqpdf/qpdf-c.cc +++ b/libqpdf/qpdf-c.cc @@ -1772,6 +1772,16 @@ qpdf_oh_get_page_content_data(qpdf_data qpdf, qpdf_oh page_oh, unsigned char** b } void +qpdf_oh_free_buffer(unsigned char** bufp) +{ + QTC::TC("qpdf", "qpdf-c called qpdf_oh_free_buffer"); + if (bufp && *bufp) { + free(*bufp); + *bufp = nullptr; + } +} + +void qpdf_oh_replace_stream_data( qpdf_data qpdf, qpdf_oh stream_oh, diff --git a/qpdf/qpdf-ctest.c b/qpdf/qpdf-ctest.c index d0c6055..73e56dd 100644 --- a/qpdf/qpdf-ctest.c +++ b/qpdf/qpdf-ctest.c @@ -1151,7 +1151,7 @@ test38(char const* infile, char const* password, char const* outfile, char const assert(qpdf_oh_get_stream_data(qpdf, stream, qpdf_dl_none, 0, &buf, &len) == 0); assert(len == 53); assert(((int)buf[0] == 'x') && ((int)buf[1] == 0234)); - free(buf); + qpdf_oh_free_buffer(&buf); /* Test whether filterable */ QPDF_BOOL filtered = QPDF_FALSE; @@ -1169,8 +1169,8 @@ test38(char const* infile, char const* password, char const* outfile, char const assert(qpdf_oh_get_page_content_data(qpdf, page2, &buf2, &len) == 0); assert(len == 47); assert(memcmp(buf, buf2, len) == 0); - free(buf); - free(buf2); + qpdf_oh_free_buffer(&buf); + qpdf_oh_free_buffer(&buf2); /* errors */ printf("page content on broken page\n"); diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 25e4dd7..6f8d556 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -627,6 +627,7 @@ qpdf-c stream data filtered set 1 qpdf-c stream data buf set 1 qpdf-c called qpdf_oh_get_page_content_data 0 qpdf-c called qpdf_oh_replace_stream_data 0 +qpdf-c called qpdf_oh_free_buffer 0 qpdf-c silence oh errors 0 qpdf-c called qpdf_oh_get_binary_string_value 0 qpdf-c called qpdf_oh_get_binary_utf8_value 0