summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_annot.c')
-rw-r--r--pdf/pdf_annot.c189
1 files changed, 138 insertions, 51 deletions
diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c
index 7b96be1c..83b79293 100644
--- a/pdf/pdf_annot.c
+++ b/pdf/pdf_annot.c
@@ -269,7 +269,7 @@ static int pdfi_annot_draw_AP(pdf_context *ctx, pdf_dict *annot, pdf_obj *NormAP
if (NormAP == NULL)
return 0;
- if (NormAP->type != PDF_STREAM)
+ if (pdfi_type_of(NormAP) != PDF_STREAM)
return_error(gs_error_typecheck);
code = pdfi_op_q(ctx);
@@ -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;
}
@@ -1475,11 +1523,13 @@ static int pdfi_annot_draw_LE(pdf_context *ctx, pdf_dict *annot,
double dx, dy;
double angle;
int code;
+ pdf_obj_type type;
code = pdfi_dict_knownget(ctx, annot, "LE", (pdf_obj **)&LE);
if (code <= 0)
goto exit;
- if (LE->type != PDF_ARRAY && LE->type != PDF_NAME) {
+ type = pdfi_type_of(LE);
+ if (type != PDF_ARRAY && type != PDF_NAME) {
code = gs_note_error(gs_error_typecheck);
goto exit;
}
@@ -1490,7 +1540,7 @@ static int pdfi_annot_draw_LE(pdf_context *ctx, pdf_dict *annot,
if (code < 0)
angle = 0;
- if (LE->type == PDF_ARRAY) {
+ if (type == PDF_ARRAY) {
code = pdfi_array_get_type(ctx, (pdf_array *)LE, 0, PDF_NAME, (pdf_obj **)&LE1);
if (code < 0) goto exit;
@@ -1554,34 +1604,35 @@ static int pdfi_annot_get_NormAP(pdf_context *ctx, pdf_dict *annot, pdf_obj **No
/* Nothing found */
if (code == 0) goto exit;
- if (baseAP->type == PDF_STREAM) {
- /* Use baseAP for the AP */
- AP = (pdf_stream *)baseAP;
- baseAP = NULL;
- } else {
- if (baseAP->type != PDF_DICT) {
- code = gs_error_typecheck;
- goto exit;
- }
-
- code = pdfi_dict_knownget_type(ctx, annot, "AS", PDF_NAME, (pdf_obj **)&AS);
- if (code < 0) goto exit;
- if (code == 0) {
- pdfi_set_warning(ctx, 0, NULL, W_PDF_ANNOT_AP_ERROR, "pdfi_annot_get_NormAP", "WARNING Annotation has non-stream AP but no AS. Don't know what to render");
- goto exit;
- }
+ switch (pdfi_type_of(baseAP)) {
+ case PDF_STREAM:
+ /* Use baseAP for the AP */
+ AP = (pdf_stream *)baseAP;
+ baseAP = NULL;
+ break;
+ case PDF_DICT:
+ code = pdfi_dict_knownget_type(ctx, annot, "AS", PDF_NAME, (pdf_obj **)&AS);
+ if (code < 0) goto exit;
+ if (code == 0) {
+ pdfi_set_warning(ctx, 0, NULL, W_PDF_ANNOT_AP_ERROR, "pdfi_annot_get_NormAP", "WARNING Annotation has non-stream AP but no AS. Don't know what to render");
+ goto exit;
+ }
- /* Lookup the AS in the NormAP and use that as the AP */
- code = pdfi_dict_get_by_key(ctx, (pdf_dict *)baseAP, AS, (pdf_obj **)&AP);
- if (code < 0) {
- /* Apparently this is not an error, just silently don't have an AP */
- code = 0;
- goto exit;
- }
- if (AP->type != PDF_STREAM) {
- code = gs_note_error(gs_error_typecheck);
+ /* Lookup the AS in the NormAP and use that as the AP */
+ code = pdfi_dict_get_by_key(ctx, (pdf_dict *)baseAP, AS, (pdf_obj **)&AP);
+ if (code < 0) {
+ /* Apparently this is not an error, just silently don't have an AP */
+ code = 0;
+ goto exit;
+ }
+ if (pdfi_type_of(AP) != PDF_STREAM) {
+ code = gs_note_error(gs_error_typecheck);
+ goto exit;
+ }
+ break;
+ default:
+ code = gs_error_typecheck;
goto exit;
- }
}
*NormAP = (pdf_obj *)AP;
@@ -3630,9 +3681,9 @@ static int pdfi_annot_draw_Widget(pdf_context *ctx, pdf_dict *annot, pdf_obj *No
{
int code = 0;
bool found_T = false;
- bool found_TF = false;
+ bool found_FT = false, known = false;
pdf_obj *T = NULL;
- pdf_obj *TF = NULL;
+ pdf_obj *FT = NULL;
pdf_dict *Parent = NULL;
pdf_dict *currdict = NULL;
@@ -3651,33 +3702,71 @@ static int pdfi_annot_draw_Widget(pdf_context *ctx, pdf_dict *annot, pdf_obj *No
/* TODO: See top part of pdf_draw.ps/drawwidget
* check for /FT and /T and stuff
*/
+ code = pdfi_loop_detector_mark(ctx);
+ if (code < 0)
+ goto exit;
+
currdict = annot;
pdfi_countup(currdict);
while (true) {
+ if (currdict->object_num != 0) {
+ code = pdfi_loop_detector_add_object(ctx, currdict->object_num);
+ if (code < 0)
+ break;
+ }
+
code = pdfi_dict_knownget(ctx, currdict, "T", &T);
if (code < 0) goto exit;
if (code > 0) {
found_T = true;
- break;
+ pdfi_countdown(T);
+ T = NULL;
+ if (found_FT)
+ break;
}
- code = pdfi_dict_knownget(ctx, currdict, "TF", &TF);
+ code = pdfi_dict_knownget(ctx, currdict, "FT", &FT);
if (code < 0) goto exit;
if (code > 0) {
- found_TF = true;
- break;
+ found_FT = true;
+ pdfi_countdown(FT);
+ FT = NULL;
+ 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) {
+ (void)pdfi_loop_detector_cleartomark(ctx);
+ 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 {
+ break;
+ }
+ }
+ pdfi_countdown(currdict);
+ currdict = Parent;
+ Parent = NULL;
+ } else
break;
- pdfi_countdown(currdict);
- currdict = Parent;
- pdfi_countup(currdict);
}
+ (void)pdfi_loop_detector_cleartomark(ctx);
+
code = 0;
- if (!found_T && !found_TF) {
+ 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");
@@ -3696,8 +3785,6 @@ static int pdfi_annot_draw_Widget(pdf_context *ctx, pdf_dict *annot, pdf_obj *No
*render_done = true;
exit:
- pdfi_countdown(T);
- pdfi_countdown(TF);
pdfi_countdown(Parent);
pdfi_countdown(currdict);
return code;
@@ -3950,7 +4037,7 @@ static int pdfi_annot_preserve_modQP(pdf_context *ctx, pdf_dict *annot, pdf_name
code = pdfi_dict_get(ctx, annot, "QuadPoints", (pdf_obj **)&QP);
if (code < 0) goto exit;
- if (QP->type != PDF_ARRAY) {
+ if (pdfi_type_of(QP) != PDF_ARRAY) {
/* Invalid QuadPoints, just delete it because I dunno what to do...
* TODO: Should flag a warning here
*/
@@ -4024,7 +4111,7 @@ static int pdfi_annot_preserve_modAP(pdf_context *ctx, pdf_dict *annot, pdf_name
code = pdfi_dict_get(ctx, annot, "AP", (pdf_obj **)&AP);
if (code < 0) goto exit;
- if (AP->type != PDF_DICT) {
+ if (pdfi_type_of(AP) != PDF_DICT) {
/* This is an invalid AP, we will flag and delete it below */
found_ap = false;
goto exit;
@@ -4037,14 +4124,14 @@ static int pdfi_annot_preserve_modAP(pdf_context *ctx, pdf_dict *annot, pdf_name
if (code < 0) goto exit;
/* Handle indirect object */
- if (Value->type != PDF_INDIRECT)
+ if (pdfi_type_of(Value) != PDF_INDIRECT)
goto loop_continue;
/* Dereference it */
code = pdfi_dereference(ctx, Value->ref_object_num, Value->ref_generation_num, &object);
if (code < 0) goto exit;
- if (object->type == PDF_STREAM) {
+ if (pdfi_type_of(object) == PDF_STREAM) {
/* Get a form label */
code = pdfi_annot_preserve_nextformlabel(ctx, &labeldata, &labellen);
if (code < 0) goto exit;