diff options
Diffstat (limited to 'pdf/pdf_image.c')
-rw-r--r-- | pdf/pdf_image.c | 165 |
1 files changed, 122 insertions, 43 deletions
diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c index 554cc344..43b70f56 100644 --- a/pdf/pdf_image.c +++ b/pdf/pdf_image.c @@ -173,7 +173,7 @@ pdfi_find_alternate(pdf_context *ctx, pdf_obj *alt) int code; bool flag; - if (alt->type != PDF_ARRAY) + if (pdfi_type_of(alt) != PDF_ARRAY) return NULL; array = (pdf_array *)alt; @@ -528,6 +528,10 @@ pdfi_get_image_info(pdf_context *ctx, pdf_stream *image_obj, } info->BPC = 1; } + else if (info->BPC != 1 && info->BPC != 2 && info->BPC != 4 && info->BPC != 8 && info->BPC != 16) { + code = gs_note_error(gs_error_rangecheck); + goto errorExit; + } /* TODO: spec says if ImageMask is specified, and BPC is specified, then BPC must be 1 Should we flag an error if this is violated? */ @@ -541,11 +545,18 @@ pdfi_get_image_info(pdf_context *ctx, pdf_stream *image_obj, * GS implementation does. */ if (code != gs_error_undefined) { - pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_IMAGEDICT, "pdfi_get_image_info", NULL); + pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_IMAGEDICT, "pdfi_get_image_info", NULL); if (ctx->args.pdfstoponwarning) goto errorExit; } } + if (info->Mask != NULL && (pdfi_type_of(info->Mask) != PDF_ARRAY && pdfi_type_of(info->Mask) != PDF_STREAM)) { + pdfi_countdown(info->Mask); + info->Mask = NULL; + pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_IMAGEDICT, "pdfi_get_image_info", NULL); + if (ctx->args.pdfstoponwarning) + goto errorExit; + } /* Optional (apparently there is no abbreviation for "SMask"? */ code = pdfi_dict_get(ctx, image_dict, "SMask", &info->SMask); @@ -558,7 +569,7 @@ pdfi_get_image_info(pdf_context *ctx, pdf_stream *image_obj, code = 0; } } else { - if (info->SMask->type == PDF_NAME) { + if (pdfi_type_of(info->SMask) == PDF_NAME) { pdf_obj *o = NULL; code = pdfi_find_resource(ctx, (unsigned char *)"ExtGState", (pdf_name *)info->SMask, image_dict, page_dict, &o); @@ -568,9 +579,12 @@ pdfi_get_image_info(pdf_context *ctx, pdf_stream *image_obj, } } - if (info->SMask->type != PDF_STREAM){ + if (pdfi_type_of(info->SMask) != PDF_STREAM){ pdfi_countdown(info->SMask); info->SMask = NULL; + pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_IMAGEDICT, "pdfi_get_image_info", NULL); + if (ctx->args.pdfstoponwarning) + goto errorExit; } } @@ -592,6 +606,13 @@ pdfi_get_image_info(pdf_context *ctx, pdf_stream *image_obj, if (code != gs_error_undefined) goto errorExit; } + if (info->ColorSpace != NULL && (pdfi_type_of(info->ColorSpace) != PDF_NAME && pdfi_type_of(info->ColorSpace) != PDF_ARRAY)) { + pdfi_countdown(info->ColorSpace); + info->ColorSpace = NULL; + pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_IMAGEDICT, "pdfi_get_image_info", NULL); + if (ctx->args.pdfstoponwarning) + goto errorExit; + } /* Optional (default is to use from graphics state) */ /* (no abbreviation for inline) */ @@ -607,6 +628,13 @@ pdfi_get_image_info(pdf_context *ctx, pdf_stream *image_obj, if (code != gs_error_undefined) goto errorExit; } + if (info->Alternates != NULL && pdfi_type_of(info->Alternates) != PDF_ARRAY) { + pdfi_countdown(info->Alternates); + info->Alternates = NULL; + pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_IMAGEDICT, "pdfi_get_image_info", NULL); + if (ctx->args.pdfstoponwarning) + goto errorExit; + } /* Optional (required in PDF1.0, obsolete, do we support?) */ code = pdfi_dict_get(ctx, image_dict, "Name", &info->Name); @@ -614,6 +642,13 @@ pdfi_get_image_info(pdf_context *ctx, pdf_stream *image_obj, if (code != gs_error_undefined) goto errorExit; } + if (info->Name != NULL && pdfi_type_of(info->Name) != PDF_NAME) { + pdfi_countdown(info->Name); + info->Name = NULL; + pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_IMAGEDICT, "pdfi_get_image_info", NULL); + if (ctx->args.pdfstoponwarning) + goto errorExit; + } /* Required "if image is structural content item" */ /* TODO: Figure out what to do here */ @@ -629,6 +664,13 @@ pdfi_get_image_info(pdf_context *ctx, pdf_stream *image_obj, if (code != gs_error_undefined) goto errorExit; } + if (info->Decode != NULL && pdfi_type_of(info->Decode) != PDF_ARRAY) { + pdfi_countdown(info->Decode); + info->Decode = NULL; + pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_IMAGEDICT, "pdfi_get_image_info", NULL); + if (ctx->args.pdfstoponwarning) + goto errorExit; + } /* Optional "Optional Content" */ code = pdfi_dict_get_type(ctx, image_dict, "OC", PDF_DICT, (pdf_obj **)&info->OC); @@ -643,10 +685,17 @@ pdfi_get_image_info(pdf_context *ctx, pdf_stream *image_obj, if (code != gs_error_undefined) goto errorExit; } + if (info->Filter != NULL && (pdfi_type_of(info->Filter) != PDF_NAME && pdfi_type_of(info->Filter) != PDF_ARRAY)) { + pdfi_countdown(info->Filter); + info->Filter = NULL; + pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_IMAGEDICT, "pdfi_get_image_info", NULL); + if (ctx->args.pdfstoponwarning) + goto errorExit; + } /* Check and set JPXDecode flag for later */ info->is_JPXDecode = false; - if (info->Filter && info->Filter->type == PDF_NAME) { + if (info->Filter && pdfi_type_of(info->Filter) == PDF_NAME) { if (pdfi_name_is((pdf_name *)info->Filter, "JPXDecode")) info->is_JPXDecode = true; } @@ -657,6 +706,13 @@ pdfi_get_image_info(pdf_context *ctx, pdf_stream *image_obj, if (code != gs_error_undefined) goto errorExit; } + if (info->DecodeParms != NULL && (pdfi_type_of(info->DecodeParms) != PDF_DICT && pdfi_type_of(info->DecodeParms) != PDF_ARRAY)) { + pdfi_countdown(info->DecodeParms); + info->DecodeParms = NULL; + pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_IMAGEDICT, "pdfi_get_image_info", NULL); + if (ctx->args.pdfstoponwarning) + goto errorExit; + } return 0; @@ -987,6 +1043,9 @@ pdfi_do_image_smask(pdf_context *ctx, pdf_c_stream *source, pdfi_image_info_t *i if (code < 0) return code; + if (pdfi_type_of(image_info->SMask) != PDF_STREAM) + return_error(gs_error_typecheck); + if (image_info->SMask->object_num != 0) { if (pdfi_loop_detector_check_object(ctx, image_info->SMask->object_num)) return gs_note_error(gs_error_circular_reference); @@ -1018,22 +1077,23 @@ pdfi_do_image_smask(pdf_context *ctx, pdf_c_stream *source, pdfi_image_info_t *i pdfi_seek(ctx, ctx->main_stream, pdfi_stream_offset(ctx, (pdf_stream *)image_info->SMask), SEEK_SET); - if (image_info->SMask->type == PDF_DICT) { - code = pdfi_obj_dict_to_stream(ctx, (pdf_dict *)image_info->SMask, &stream_obj, false); - if (code == 0) { - code = pdfi_do_image_or_form(ctx, image_info->stream_dict, - image_info->page_dict, (pdf_obj *)stream_obj); + switch (pdfi_type_of(image_info->SMask)) { + case PDF_DICT: + code = pdfi_obj_dict_to_stream(ctx, (pdf_dict *)image_info->SMask, &stream_obj, false); + if (code == 0) { + code = pdfi_do_image_or_form(ctx, image_info->stream_dict, + image_info->page_dict, (pdf_obj *)stream_obj); - pdfi_countdown(stream_obj); - } - } else { - if (image_info->SMask->type == PDF_STREAM) + pdfi_countdown(stream_obj); + } + break; + case PDF_STREAM: code = pdfi_do_image_or_form(ctx, image_info->stream_dict, image_info->page_dict, image_info->SMask); - else { + break; + default: code = gs_note_error(gs_error_typecheck); goto exit; - } } pdfi_seek(ctx, ctx->main_stream, savedoffset, SEEK_SET); @@ -1434,7 +1494,7 @@ pdfi_image_get_color(pdf_context *ctx, pdf_c_stream *source, pdfi_image_info_t * pcs, image_info->inline_image); if (code < 0) { dmprintf(ctx->memory, "WARNING: Image has unsupported ColorSpace "); - if (ColorSpace->type == PDF_NAME) { + if (pdfi_type_of(ColorSpace) == PDF_NAME) { pdf_name *name = (pdf_name *)ColorSpace; char str[100]; int length = name->length; @@ -1496,7 +1556,7 @@ pdfi_make_smask_dict(pdf_context *ctx, pdf_stream *image_stream, pdfi_image_info goto exit; } - if (image_stream->type != PDF_STREAM) { + if (pdfi_type_of(image_stream) != PDF_STREAM) { code = gs_note_error(gs_error_typecheck); goto exit; } @@ -1623,7 +1683,7 @@ pdfi_do_image(pdf_context *ctx, pdf_dict *page_dict, pdf_dict *stream_dict, pdf_ memset(&smask_info, 0, sizeof(mask_info)); /* Make sure the image is a stream (which we will assume in later code) */ - if (image_stream->type != PDF_STREAM) + if (pdfi_type_of(image_stream) != PDF_STREAM) return_error(gs_error_typecheck); if (!inline_image) { @@ -1867,23 +1927,26 @@ pdfi_do_image(pdf_context *ctx, pdf_dict *page_dict, pdf_dict *stream_dict, pdf_ /* Get the Mask data either as an array or a dict, if present */ if (image_info.Mask != NULL) { - if (image_info.Mask->type == PDF_ARRAY) { - mask_array = (pdf_array *)image_info.Mask; - } else if (image_info.Mask->type == PDF_STREAM) { - mask_stream = (pdf_stream *)image_info.Mask; - code = pdfi_get_image_info(ctx, mask_stream, page_dict, - stream_dict, inline_image, &mask_info); - if (code < 0) - goto cleanupExit; - } else { - pdfi_countdown(image_info.Mask); - image_info.Mask = NULL; - pdfi_set_warning(ctx, 0, NULL, W_PDF_MASK_ERROR, "pdfi_do_image", NULL); + switch (pdfi_type_of(image_info.Mask)) { + case PDF_ARRAY: + mask_array = (pdf_array *)image_info.Mask; + break; + case PDF_STREAM: + mask_stream = (pdf_stream *)image_info.Mask; + code = pdfi_get_image_info(ctx, mask_stream, page_dict, + stream_dict, inline_image, &mask_info); + if (code < 0) + goto cleanupExit; + break; + default: + pdfi_countdown(image_info.Mask); + image_info.Mask = NULL; + pdfi_set_warning(ctx, 0, NULL, W_PDF_MASK_ERROR, "pdfi_do_image", NULL); } } /* Get the SMask info if we will need it (Type 3x images) */ - if (image_info.SMask && image_info.SMask->type == PDF_STREAM && ctx->device_state.preserve_smask) { + if (image_info.SMask && pdfi_type_of(image_info.SMask) == PDF_STREAM && ctx->device_state.preserve_smask) { /* smask_dict non-NULL is used to flag a Type 3x image below */ smask_stream = (pdf_stream *)image_info.SMask; code = pdfi_get_image_info(ctx, smask_stream, page_dict, stream_dict, @@ -2305,7 +2368,7 @@ static int pdfi_form_stream_hack(pdf_context *ctx, pdf_dict *form_dict, pdf_stre *hacked_stream = NULL; - if (form_dict->type == PDF_STREAM) + if (pdfi_type_of(form_dict) == PDF_STREAM) return 0; if (!ctx->args.pdfstoponerror) { @@ -2325,7 +2388,7 @@ static int pdfi_form_stream_hack(pdf_context *ctx, pdf_dict *form_dict, pdf_stre pdfi_countup(d); do { code = pdfi_dict_knownget(ctx, d, "Parent", (pdf_obj **)&Parent); - if (code > 0) { + if (code > 0 && pdfi_type_of(Parent) == PDF_DICT) { if (Parent->object_num == stream_obj->object_num) { pdfi_countdown(d); pdfi_countdown(Parent); @@ -2386,7 +2449,7 @@ static int pdfi_do_form(pdf_context *ctx, pdf_dict *page_dict, pdf_stream *form_ #if DEBUG_IMAGES dbgmprintf(ctx->memory, "pdfi_do_form BEGIN\n"); #endif - if (form_obj->type != PDF_STREAM) { + if (pdfi_type_of(form_obj) != PDF_STREAM) { code = pdfi_form_stream_hack(ctx, (pdf_dict *)form_obj, &hacked_stream); if (code < 0) return code; @@ -2530,10 +2593,15 @@ int pdfi_do_image_or_form(pdf_context *ctx, pdf_dict *stream_dict, else goto exit; } + if (pdfi_type_of(n) != PDF_NAME) { + code = gs_note_error(gs_error_typecheck); + goto exit; + } + if (pdfi_name_is(n, "Image")) { gs_offset_t savedoffset; - if (xobject_obj->type != PDF_STREAM) { + if (pdfi_type_of(xobject_obj) != PDF_STREAM) { code = gs_note_error(gs_error_typecheck); goto exit; } @@ -2568,14 +2636,17 @@ int pdfi_Do(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict) pdf_name *n = NULL; pdf_obj *o = NULL; pdf_dict *sdict = NULL; - bool known = false; + bool known = false, AddedParent = false; if (pdfi_count_stack(ctx) < 1) { code = gs_note_error(gs_error_stackunderflow); goto exit1; } n = (pdf_name *)ctx->stack_top[-1]; - if (n->type != PDF_NAME) { + pdfi_countup(n); + pdfi_pop(ctx, 1); + + if (pdfi_type_of(n) != PDF_NAME) { code = gs_note_error(gs_error_typecheck); goto exit1; } @@ -2590,7 +2661,7 @@ int pdfi_Do(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict) if (code < 0) goto exit; - if (o->type != PDF_STREAM && o->type != PDF_DICT) { + if (pdfi_type_of(o) != PDF_STREAM && pdfi_type_of(o) != PDF_DICT) { code = gs_note_error(gs_error_typecheck); goto exit; } @@ -2610,9 +2681,11 @@ int pdfi_Do(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict) code = pdfi_dict_put(ctx, sdict, "Parent", (pdf_obj *)stream_dict); if (code < 0) goto exit; + pdfi_countup(sdict); + AddedParent = true; } - code = pdfi_loop_detector_cleartomark(ctx); + (void)pdfi_loop_detector_cleartomark(ctx); /* NOTE: Used to have a pdfi_gsave/pdfi_grestore around this, but it actually makes * things render incorrectly (and isn't in the PS code). * It also causes demo.ai.pdf to crash. @@ -2627,15 +2700,21 @@ int pdfi_Do(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict) // pdfi_gsave(ctx); code = pdfi_do_image_or_form(ctx, stream_dict, page_dict, o); // pdfi_grestore(ctx); + pdfi_countdown(n); pdfi_countdown(o); - pdfi_pop(ctx, 1); + if (AddedParent == true) { + if (code >= 0) + code = pdfi_dict_delete(ctx, sdict, "Parent"); + else + (void)pdfi_dict_delete(ctx, sdict, "Parent"); + pdfi_countdown(sdict); + } return code; exit: (void)pdfi_loop_detector_cleartomark(ctx); exit1: - /* No need to countdown 'n' because that points to the stack object, and we're going to pop that */ + pdfi_countdown(n); pdfi_countdown(o); - pdfi_pop(ctx, 1); return code; } |