summaryrefslogtreecommitdiff
path: root/pdf/pdf_page.c
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2022-08-24 09:19:47 +0100
committerKen Sharp <ken.sharp@artifex.com>2022-08-24 09:19:47 +0100
commit21b9a273b4aa94d88eb0c9731d339af1decce2cc (patch)
treecf3b27da41020aac5b576e83d8e48335fcb1c98b /pdf/pdf_page.c
parent10d1e337bc81c850a243e582e6a2edd043c63c16 (diff)
downloadghostpdl-21b9a273b4aa94d88eb0c9731d339af1decce2cc.tar.gz
GhostPDF - fix memory leak with malformed PDF files
Using the file from OSS-fuzz #47753 and this command line: -K1048576 -r200x200 -sBandListStorage=memory -dMaxBitmap=0 -dBufferSpace=450k -dMediaPosition=1 -dcupsColorSpace=1 -dSAFER -dNOPAUSE -dBATCH -dNOINTERPOLATE -dNOMEDIAATTRS -sDEVICE=nullpage Leaked memory due to the array checking of the various Box parameters. One of the MediaBox entries is an (invalid) indirect reference to the Pages tree, when we fetched the reference from the array we dereferenced it and stored the dereferenced value in the MediaBox array, thus creating a circular reference: Pages->Page->MediaBox ^ | |------------ Which meant we never counted down any of the objects in the sequence to 0 and freed them. Using the 'no_store_R' variant avoids storing the dereferenced object back to the array. Since we don't need the object, other than to get its numeric value, this doesn't cost any performance.
Diffstat (limited to 'pdf/pdf_page.c')
-rw-r--r--pdf/pdf_page.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c
index c7fc49524..311d75d2c 100644
--- a/pdf/pdf_page.c
+++ b/pdf/pdf_page.c
@@ -515,8 +515,14 @@ int pdfi_page_info(pdf_context *ctx, uint64_t page_num, pdf_dict **info, bool ex
pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_MEDIABOX, "pdfi_page_info", NULL);
if (code >= 0) {
+ pdf_obj *box_obj = NULL;
+
for (i = 0;i < pdfi_array_size(a); i++) {
- code = pdfi_array_get_number(ctx, a, i, &dummy);
+ code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
+ if (code >= 0) {
+ code = pdfi_obj_to_real(ctx, box_obj, &dummy);
+ pdfi_countdown(box_obj);
+ }
if (code < 0) {
pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_MEDIABOX, "pdfi_page_info", NULL);
goto done;
@@ -532,8 +538,14 @@ int pdfi_page_info(pdf_context *ctx, uint64_t page_num, pdf_dict **info, bool ex
code = pdfi_dict_get_type(ctx, page_dict, "ArtBox", PDF_ARRAY, (pdf_obj **)&a);
if (code >= 0) {
+ pdf_obj *box_obj = NULL;
+
for (i = 0;i < pdfi_array_size(a); i++) {
- code = pdfi_array_get_number(ctx, a, i, &dummy);
+ code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
+ if (code >= 0) {
+ code = pdfi_obj_to_real(ctx, box_obj, &dummy);
+ pdfi_countdown(box_obj);
+ }
if (code < 0)
break;
}
@@ -548,8 +560,14 @@ int pdfi_page_info(pdf_context *ctx, uint64_t page_num, pdf_dict **info, bool ex
code = pdfi_dict_get_type(ctx, page_dict, "CropBox", PDF_ARRAY, (pdf_obj **)&a);
if (code >= 0) {
+ pdf_obj *box_obj = NULL;
+
for (i = 0;i < pdfi_array_size(a); i++) {
- code = pdfi_array_get_number(ctx, a, i, &dummy);
+ code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
+ if (code >= 0) {
+ code = pdfi_obj_to_real(ctx, box_obj, &dummy);
+ pdfi_countdown(box_obj);
+ }
if (code < 0)
break;
}
@@ -564,8 +582,14 @@ int pdfi_page_info(pdf_context *ctx, uint64_t page_num, pdf_dict **info, bool ex
code = pdfi_dict_get_type(ctx, page_dict, "TrimBox", PDF_ARRAY, (pdf_obj **)&a);
if (code >= 0) {
+ pdf_obj *box_obj = NULL;
+
for (i = 0;i < pdfi_array_size(a); i++) {
- code = pdfi_array_get_number(ctx, a, i, &dummy);
+ code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
+ if (code >= 0) {
+ code = pdfi_obj_to_real(ctx, box_obj, &dummy);
+ pdfi_countdown(box_obj);
+ }
if (code < 0)
break;
}
@@ -580,8 +604,14 @@ int pdfi_page_info(pdf_context *ctx, uint64_t page_num, pdf_dict **info, bool ex
code = pdfi_dict_get_type(ctx, page_dict, "BleedBox", PDF_ARRAY, (pdf_obj **)&a);
if (code >= 0) {
+ pdf_obj *box_obj = NULL;
+
for (i = 0;i < pdfi_array_size(a); i++) {
- code = pdfi_array_get_number(ctx, a, i, &dummy);
+ code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
+ if (code >= 0) {
+ code = pdfi_obj_to_real(ctx, box_obj, &dummy);
+ pdfi_countdown(box_obj);
+ }
if (code < 0)
break;
}