diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2022-08-24 09:19:47 +0100 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2022-08-24 09:19:47 +0100 |
commit | 21b9a273b4aa94d88eb0c9731d339af1decce2cc (patch) | |
tree | cf3b27da41020aac5b576e83d8e48335fcb1c98b /pdf/pdf_page.c | |
parent | 10d1e337bc81c850a243e582e6a2edd043c63c16 (diff) | |
download | ghostpdl-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.c | 40 |
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; } |