diff options
Diffstat (limited to 'pdf/pdf_gstate.c')
-rw-r--r-- | pdf/pdf_gstate.c | 114 |
1 files changed, 51 insertions, 63 deletions
diff --git a/pdf/pdf_gstate.c b/pdf/pdf_gstate.c index 7544aa48..c1444b4b 100644 --- a/pdf/pdf_gstate.c +++ b/pdf/pdf_gstate.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2021 Artifex Software, Inc. +/* Copyright (C) 2018-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -17,6 +17,7 @@ #include "pdf_int.h" #include "pdf_doc.h" +#include "pdf_font_types.h" #include "pdf_gstate.h" #include "pdf_stack.h" #include "pdf_dict.h" @@ -113,7 +114,9 @@ pdfi_gstate_copy_cb(void *to, const void *from) */ if (igs_to != NULL) { pdfi_gstate_smask_free(igs_to); + pdfi_countdown(igs_to->current_font); *(pdfi_int_gstate *) igs_to = *igs_from; + pdfi_countup(igs_to->current_font); pdfi_gstate_smask_install(igs_to, igs_from->memory, igs_from->SMask, igs_from->GroupGState); } return 0; @@ -127,6 +130,7 @@ pdfi_gstate_free_cb(void *old, gs_memory_t * mem, gs_gstate *pgs) if (old == NULL) return; pdfi_gstate_smask_free(igs); + pdfi_countdown(igs->current_font); /* We need to use the graphics state memory, in case we are running under Ghostscript. */ gs_free_object(pgs->memory, igs, "pdfi_gstate_free"); } @@ -145,6 +149,8 @@ pdfi_gstate_set_client(pdf_context *ctx, gs_gstate *pgs) /* We need to use the graphics state memory, in case we are running under Ghostscript. */ igs = pdfi_gstate_alloc_cb(pgs->memory); + if (igs == NULL) + return_error(gs_error_VMerror); igs->ctx = ctx; gs_gstate_set_client(pgs, igs, &pdfi_gstate_procs, true /* TODO: client_has_pattern_streams ? */); return 0; @@ -252,93 +258,38 @@ int pdfi_op_Q(pdf_context *ctx) return code; } +/* We want pdfi_grestore() so we can track and warn of "too many Qs" + * in the interests of symmetry, we also have pdfi_gsave() + */ int pdfi_gsave(pdf_context *ctx) { - int code; - - code = gs_gsave(ctx->pgs); - - if(code < 0) - return code; - else { - pdfi_countup_current_font(ctx); - return 0; - } + return gs_gsave(ctx->pgs); } int pdfi_grestore(pdf_context *ctx) { - int code; - pdf_font *font = NULL, *font1 = NULL; + int code = 0; /* Make sure we have encountered as many gsave operations in this * stream as grestores. If not, log an error */ if (ctx->pgs->level > ctx->current_stream_save.gsave_level) { - font = pdfi_get_current_pdf_font(ctx); - code = gs_grestore(ctx->pgs); - - font1 = pdfi_get_current_pdf_font(ctx); - if (font != NULL && (font != font1 || ((pdf_obj *)font)->refcnt > 1)) { - /* TODO: This countdown might have been causing memory corruption (dangling pointer) - * but seems to be okay now. Maybe was fixed by other memory issue. 8-28-19 - * If you come upon this comment in the future and it all seems fine, feel free to - * clean this up... (delete comment, remove the commented out warning message, etc) - */ -#if REFCNT_DEBUG - dbgmprintf2(ctx->memory, "pdfi_grestore() counting down font UID %ld, refcnt %d\n", - font->UID, font->refcnt); -#endif - // dbgmprintf(ctx->memory, "WARNING pdfi_grestore() DISABLED pdfi_countdown (FIXME!)\n"); - pdfi_countdown(font); - } - - return code; } else { /* We don't throw an error here, we just ignore it and continue */ pdfi_set_warning(ctx, 0, NULL, W_PDF_TOOMANYQ, "pdfi_grestore", (char *)"ignoring q"); } - return 0; + return code; } -/* gs_setgstate is somewhat unpleasant from our point of view, because it replaces - * the content of the graphics state, without going through our pdfi_gsave/pdfi_grestore - * functionaltiy. In particular we replace the current font in the graphics state when - * we call it, and this means we *don't* count down the PDF_font object reference count - * which leads to an incorrect count and either memory leaks or early freeing. - * This function *requires* that the calling function will do a pdfi_gsave *before* - * calling pdfi_setgstate, and a pdfi_grestore *after* calling pdfi_gs_setgstate. - * it correctly increments/decrements the font reference counts for that condition - * and no other. - */ int pdfi_gs_setgstate(gs_gstate * pgs, const gs_gstate * pfrom) { - pdf_font *font = NULL; int code = 0; - /* We are going to release a reference to the font from the graphics state - * (if there is one) so count it down to keep things straight. - */ - if (pgs->font) { - font = (pdf_font *)pgs->font->client_data; - if (font) - pdfi_countdown(font); - } - code = gs_setgstate(pgs, pfrom); if (code < 0) return code; - /* The copied gstate may have contained a font, and we expect to do a - * pdfi_grestore on exit from here, which will count down the font - * so count it up now in preparation. - */ - if (pgs->font) { - font = (pdf_font *)pgs->font->client_data; - if (font) - pdfi_countup(font); - } return code; } @@ -924,6 +875,11 @@ static int pdfi_set_all_transfers(pdf_context *ctx, pdf_array *a, pdf_dict *page pdfi_countdown(o); goto exit; } + if (pfn[i]->params.m != 1 || pfn[i]->params.n != 1) { + pdfi_countdown(o); + code = gs_note_error(gs_error_rangecheck); + goto exit; + } } else { pdfi_countdown(o); code = gs_note_error(gs_error_typecheck); @@ -987,7 +943,6 @@ static int pdfi_set_all_transfers(pdf_context *ctx, pdf_array *a, pdf_dict *page } } exit: -// (void)pdfi_seek(ctx, ctx->main_stream, saved_stream_offset, SEEK_SET); for (i = 0; i < 4; i++) { pdfi_free_function(ctx, pfn[i]); } @@ -1006,6 +961,11 @@ static int pdfi_set_gray_transfer(pdf_context *ctx, pdf_obj *tr_obj, pdf_dict *p if (code < 0) return code; + if (pfn->params.m != 1 || pfn->params.n != 1) { + (void)pdfi_free_function(ctx, pfn); + return_error(gs_error_rangecheck); + } + gs_settransfer_remap(ctx->pgs, gs_mapped_transfer, false); for (i = 0; i < transfer_map_size; i++) { float v, f; @@ -1206,6 +1166,7 @@ static int build_type1_halftone(pdf_context *ctx, pdf_dict *halftone_dict, pdf_d gs_screen_enum *penum = NULL; gs_point pt; gx_transfer_map *pmap = NULL; + bool as; code = pdfi_dict_get_number(ctx, halftone_dict, "Frequency", &f); if (code < 0) @@ -1219,6 +1180,12 @@ static int build_type1_halftone(pdf_context *ctx, pdf_dict *halftone_dict, pdf_d if (code < 0) return code; + code = pdfi_dict_get_bool(ctx, halftone_dict, "AccurateScreens", &as); + if (code == gs_error_undefined) + as = 0; + else if (code < 0) + return code; + order = (gx_ht_order *)gs_alloc_bytes(ctx->memory, sizeof(gx_ht_order), "build_type1_halftone"); if (order == NULL) { code = gs_note_error(gs_error_VMerror); @@ -1275,6 +1242,7 @@ static int build_type1_halftone(pdf_context *ctx, pdf_dict *halftone_dict, pdf_d phtc->params.spot.transfer = (code > 0 ? (gs_mapping_proc) 0 : gs_mapped_transfer); phtc->params.spot.transfer_closure.proc = 0; phtc->params.spot.transfer_closure.data = 0; + phtc->params.spot.accurate_screens = as; phtc->type = ht_type_spot; code = pdfi_get_name_index(ctx, name, len, (unsigned int *)&phtc->cname); if (code < 0) @@ -2199,6 +2167,16 @@ static int GS_CA(pdf_context *ctx, pdf_dict *GS, pdf_dict *stream_dict, pdf_dict if (code < 0) return code; + if (d1 > 1.0) { + pdfi_set_warning(ctx, 0, NULL, W_PDF_CA_OUTOFRANGE, "GS_CA", NULL); + d1 = 1.0; + } + + if (d1 < 0.0) { + pdfi_set_warning(ctx, 0, NULL, W_PDF_CA_OUTOFRANGE, "GS_CA", NULL); + d1 = 0.0; + } + code = gs_setstrokeconstantalpha(ctx->pgs, d1); return code; } @@ -2212,6 +2190,16 @@ static int GS_ca(pdf_context *ctx, pdf_dict *GS, pdf_dict *stream_dict, pdf_dict if (code < 0) return code; + if (d1 > 1.0) { + pdfi_set_warning(ctx, 0, NULL, W_PDF_CA_OUTOFRANGE, "GS_ca", NULL); + d1 = 1.0; + } + + if (d1 < 0.0) { + pdfi_set_warning(ctx, 0, NULL, W_PDF_CA_OUTOFRANGE, "GS_ca", NULL); + d1 = 0.0; + } + code = gs_setfillconstantalpha(ctx->pgs, d1); return code; } |