summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2022-08-16 16:18:45 +0100
committerKen Sharp <ken.sharp@artifex.com>2022-08-16 16:18:45 +0100
commit461818d4af16839b9cd8c68320fc224f66d76691 (patch)
treef0e721f55f9e4ba3fbdede329ea472bc0c7d9fd1
parent203fc04f3079ef07a61c3f90bcc124d0568c4887 (diff)
downloadghostpdl-461818d4af16839b9cd8c68320fc224f66d76691.tar.gz
GhostPDF - more work on Widget annotations
The first problem is that the code did not do what the comments said. We exited the loop searching for T and FT keys as soon as we found either, and then only checked if we had at least one of the keys. The comments (and the old PostScript code) say we should not render the annotation unless both keys are present. Change the loop and exit conditions to implement this. The second change is handling the /Parent. If we use a simple dictionary accessor then the value of the key will be dereferenced and stored in the dictionary. Fine if the Parent is valid but if the Parent value is an indirect reference to (eg) the Pages tree, then we will end up with a circular reference (Pages->Page->annot->Pages) which will leak memory. Use more complicated code to access the dictionary without storing the dereferenced value of /Parent in the dictionary.
-rw-r--r--pdf/pdf_annot.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c
index 63667d517..bb5d6c410 100644
--- a/pdf/pdf_annot.c
+++ b/pdf/pdf_annot.c
@@ -3632,8 +3632,8 @@ static int pdfi_annot_render_Widget(pdf_context *ctx, pdf_dict *annot)
static int pdfi_annot_draw_Widget(pdf_context *ctx, pdf_dict *annot, pdf_obj *NormAP, bool *render_done)
{
int code = 0;
- bool found_T = false;
- bool found_FT = false;
+ bool found_T = true;
+ bool found_FT = true, known = false;
pdf_obj *T = NULL;
pdf_obj *FT = NULL;
pdf_dict *Parent = NULL;
@@ -3661,26 +3661,47 @@ static int pdfi_annot_draw_Widget(pdf_context *ctx, pdf_dict *annot, pdf_obj *No
if (code < 0) goto exit;
if (code > 0) {
found_T = true;
- break;
+ if (found_FT)
+ break;
}
code = pdfi_dict_knownget(ctx, currdict, "FT", &FT);
if (code < 0) goto exit;
if (code > 0) {
found_FT = true;
- break;
+ if (found_T)
+ break;
}
- /* Check for Parent */
- code = pdfi_dict_knownget_type(ctx, currdict, "Parent", PDF_DICT, (pdf_obj **)&Parent);
- if (code < 0) goto exit;
- if (code == 0)
+ /* Check for Parent. Do not store the dereferenced Parent back to the dictionary
+ * as this can cause circular references.
+ */
+ code = pdfi_dict_known(ctx, currdict, "Parent", &known);
+ if (code >= 0 && known == true)
+ {
+ code = pdfi_dict_get_no_store_R(ctx, currdict, "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);
+ if (code < 0)
+ break;
+ } else {
+ pdfi_countdown(Parent);
+ break;
+ }
+ }
+ pdfi_countdown(currdict);
+ currdict = Parent;
+ pdfi_countup(currdict);
+ } else
break;
- pdfi_countdown(currdict);
- currdict = Parent;
- pdfi_countup(currdict);
}
code = 0;
- if (!found_T && !found_FT) {
+ if (!found_T || !found_FT) {
*render_done = true;
dmprintf(ctx->memory, "**** Warning: A Widget annotation dictionary lacks either the FT or T key.\n");
dmprintf(ctx->memory, " Acrobat ignores such annoataions, annotation will not be rendered.\n");