diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2022-09-06 11:31:40 +0100 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2022-09-06 16:58:55 +0100 |
commit | 6251c3db68efb1482451f0383121ea20eb73c782 (patch) | |
tree | 011ebae8207f9ebf233b77948f9e81fa4a32140e | |
parent | a6ed2d417205ddf4194a2385402a5c97fe991013 (diff) | |
download | ghostpdl-6251c3db68efb1482451f0383121ea20eb73c782.tar.gz |
GhostPDF - yet more meddling with /Parent
OSS-fuzz 51011
The annot and optional content code all use the /Parent dictionary, but
doesn't have any circular reference protection.
This duplicates the protection we added to Widget annotations. I intend
to supercede this commit with a more general one which deals in a more
common fashion with access to the /Parent, I just don't want to lose
this commit.
-rw-r--r-- | pdf/pdf_annot.c | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c index e24abd8ef..83b79293d 100644 --- a/pdf/pdf_annot.c +++ b/pdf/pdf_annot.c @@ -649,11 +649,55 @@ static int pdfi_form_get_inheritable(pdf_context *ctx, pdf_dict *field, const ch { int code = 0; pdf_dict *Parent = NULL; + bool known = false; /* Check this field */ code = pdfi_dict_knownget_type(ctx, field, Key, type, o); - if (code != 0) goto exit; + if (code != 0) goto exit1; + code = pdfi_loop_detector_mark(ctx); + if (code < 0) + goto exit; + + /* Check for Parent. Do not store the dereferenced Parent back to the dictionary + * as this can cause circular references. + */ + code = pdfi_dict_known(ctx, field, "Parent", &known); + if (code >= 0 && known == true) + { + code = pdfi_dict_get_no_store_R(ctx, field, "Parent", (pdf_obj **)&Parent); + if (code < 0) + goto exit; + + if (pdfi_type_of(Parent) != PDF_DICT) { + if (pdfi_type_of(Parent) == PDF_INDIRECT) { + pdf_indirect_ref *o = (pdf_indirect_ref *)Parent; + + code = pdfi_dereference(ctx, o->ref_object_num, o->ref_generation_num, (pdf_obj **)&Parent); + pdfi_countdown(o); + goto exit; + } else { + code = gs_note_error(gs_error_typecheck); + goto exit; + } + } + if (Parent->object_num != 0) { + code = pdfi_loop_detector_add_object(ctx, Parent->object_num); + if (code < 0) + goto exit; + } + code = pdfi_form_get_inheritable(ctx, Parent, Key, type, o); + if (code <= 0) { + if (ctx->AcroForm) + code = pdfi_dict_knownget_type(ctx, ctx->AcroForm, Key, type, o); + } + } else { + /* No Parent, so check AcroForm, if any */ + if (ctx->AcroForm) + code = pdfi_dict_knownget_type(ctx, ctx->AcroForm, Key, type, o); + } + +#if 0 /* If not found, recursively check Parent, if any */ code = pdfi_dict_knownget_type(ctx, field, "Parent", PDF_DICT, (pdf_obj **)&Parent); if (code < 0) goto exit; @@ -665,8 +709,12 @@ static int pdfi_form_get_inheritable(pdf_context *ctx, pdf_dict *field, const ch if (ctx->AcroForm) code = pdfi_dict_knownget_type(ctx, ctx->AcroForm, Key, type, o); } +#endif - exit: +exit: + (void)pdfi_loop_detector_cleartomark(ctx); + +exit1: pdfi_countdown(Parent); return code; } |