From bd82b209015944abaff6738ad29a5e0353e0371e Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jan 31 2019 17:05:21 +0000 Subject: import ghostscript-9.07-31.el7_6.9 --- diff --git a/SOURCES/ghostscript-cve-2018-16540.patch b/SOURCES/ghostscript-cve-2018-16540.patch new file mode 100644 index 0000000..788827e --- /dev/null +++ b/SOURCES/ghostscript-cve-2018-16540.patch @@ -0,0 +1,108 @@ +From: Chris Liddell +Date: Thu, 23 Aug 2018 13:13:25 +0000 (+0100) +Subject: Bug 699661: Avoid sharing pointers between pdf14 compositors + +Bug 699661: Avoid sharing pointers between pdf14 compositors + +If a copdevice is triggered when the pdf14 compositor is the device, we make +a copy of the device, then throw an error because, by default we're only allowed +to copy the device prototype - then freeing it calls the finalize, which frees +several pointers shared with the parent. + +Make a pdf14 specific finish_copydevice() which NULLs the relevant pointers, +before, possibly, throwing the same error as the default method. + +This also highlighted a problem with reopening the X11 devices, where a custom +error handler could be replaced with itself, meaning it also called itself, +and infifite recursion resulted. + +Keep a note of if the handler replacement has been done, and don't do it a +second time. + +https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=c432131c3fdb2143e148e8ba88555f7f7a63b25e +--- + +diff -up ghostscript-9.07/base/gdevp14.c.cve-2018-16540 ghostscript-9.07/base/gdevp14.c +--- ghostscript-9.07/base/gdevp14.c.cve-2018-16540 2019-01-14 12:57:56.324331784 +0100 ++++ ghostscript-9.07/base/gdevp14.c 2019-01-14 13:00:38.224433442 +0100 +@@ -176,6 +176,7 @@ static dev_proc_fill_mask(pdf14_fill_mas + static dev_proc_stroke_path(pdf14_stroke_path); + static dev_proc_begin_typed_image(pdf14_begin_typed_image); + static dev_proc_text_begin(pdf14_text_begin); ++static dev_proc_finish_copydevice(pdf14_finish_copydevice); + static dev_proc_create_compositor(pdf14_create_compositor); + static dev_proc_create_compositor(pdf14_forward_create_compositor); + static dev_proc_begin_transparency_group(pdf14_begin_transparency_group); +@@ -246,7 +247,7 @@ static const gx_color_map_procs * + pdf14_create_compositor, /* create_compositor */\ + NULL, /* get_hardware_params */\ + pdf14_text_begin, /* text_begin */\ +- NULL, /* finish_copydevice */\ ++ pdf14_finish_copydevice, /* finish_copydevice */\ + pdf14_begin_transparency_group,\ + pdf14_end_transparency_group,\ + pdf14_begin_transparency_mask,\ +@@ -3217,6 +3218,19 @@ pdf14_text_begin(gx_device * dev, gs_ima + return code; + } + ++static int ++pdf14_finish_copydevice(gx_device *new_dev, const gx_device *from_dev) ++{ ++ pdf14_device *pdev = (pdf14_device*)new_dev; ++ ++ pdev->ctx = NULL; ++ pdev->trans_group_parent_cmap_procs = NULL; ++ pdev->smaskcolor = NULL; ++ ++ /* Only allow copying the prototype. */ ++ return (from_dev->memory ? gs_note_error(gs_error_rangecheck) : 0); ++} ++ + /* + * Implement copy_mono by filling lots of small rectangles. + */ +@@ -7499,6 +7513,7 @@ c_pdf14trans_clist_read_update(gs_compos + before reopening the device */ + if (p14dev->ctx != NULL) { + pdf14_ctx_free(p14dev->ctx); ++ p14dev->ctx = NULL; + } + dev_proc(tdev, open_device) (tdev); + } +diff -up ghostscript-9.07/base/gdevxini.c.cve-2018-16540 ghostscript-9.07/base/gdevxini.c +--- ghostscript-9.07/base/gdevxini.c.cve-2018-16540 2019-01-14 13:01:43.310670279 +0100 ++++ ghostscript-9.07/base/gdevxini.c 2019-01-14 13:04:10.937939293 +0100 +@@ -59,7 +59,8 @@ static struct xv_ { + Boolean alloc_error; + XErrorHandler orighandler; + XErrorHandler oldhandler; +-} x_error_handler; ++ Boolean set; ++} x_error_handler = {0}; + + static int + x_catch_alloc(Display * dpy, XErrorEvent * err) +@@ -74,7 +75,8 @@ x_catch_alloc(Display * dpy, XErrorEvent + int + x_catch_free_colors(Display * dpy, XErrorEvent * err) + { +- if (err->request_code == X_FreeColors) ++ if (err->request_code == X_FreeColors || ++ x_error_handler.orighandler == x_catch_free_colors) + return 0; + return x_error_handler.orighandler(dpy, err); + } +@@ -274,8 +276,10 @@ gdev_x_open(gx_device_X * xdev) + return_error(gs_error_ioerror); + } + /* Buggy X servers may cause a Bad Access on XFreeColors. */ +- x_error_handler.orighandler = XSetErrorHandler(x_catch_free_colors); +- ++ if (!x_error_handler.set) { ++ x_error_handler.orighandler = XSetErrorHandler(x_catch_free_colors); ++ x_error_handler.set = True; ++ } + /* Get X Resources. Use the toolkit for this. */ + XtToolkitInitialize(); + app_con = XtCreateApplicationContext(); diff --git a/SOURCES/ghostscript-cve-2018-19475.patch b/SOURCES/ghostscript-cve-2018-19475.patch new file mode 100644 index 0000000..cb9256a --- /dev/null +++ b/SOURCES/ghostscript-cve-2018-19475.patch @@ -0,0 +1,26 @@ +From: Chris Liddell +Date: Mon, 12 Nov 2018 17:21:33 +0000 (+0000) +Subject: Bug 700153: restore: always check available stack + +Bug 700153: restore: always check available stack + +Previously, we were checking there was enough stack space available when the +restore operation required a device change, but since we have to use +Postscript to reset the userparams (ick!), we need the stack check even when +not changing the device. + +https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=3005fcb9bb160af199e761e03bc70a9f249a987e +--- + +diff -up ghostscript-9.07/psi/zdevice2.c.cve-2018-19475 ghostscript-9.07/psi/zdevice2.c +--- ghostscript-9.07/psi/zdevice2.c.cve-2018-19475 2019-01-14 14:28:02.359841826 +0100 ++++ ghostscript-9.07/psi/zdevice2.c 2019-01-14 14:29:29.939816553 +0100 +@@ -276,7 +276,7 @@ restore_page_device(i_ctx_t *i_ctx_p, co + samepagedevice = false; + } + +- if (LockSafetyParams && !samepagedevice) { ++ if (LockSafetyParams) { + const int required_ops = 512; + const int required_es = 32; + diff --git a/SOURCES/ghostscript-cve-2018-19476.patch b/SOURCES/ghostscript-cve-2018-19476.patch new file mode 100644 index 0000000..67d2ab1 --- /dev/null +++ b/SOURCES/ghostscript-cve-2018-19476.patch @@ -0,0 +1,232 @@ +From: Ken Sharp +Date: Wed, 14 Nov 2018 09:25:13 +0000 (+0000) +Subject: Bug #700169 - unchecked type + +Bug #700169 - unchecked type + +Bug #700169 "Type confusion in setcolorspace" + +In seticc() we extract "Name" from a dictionary, if it succeeds we then +use it as a string, without checking the type to see if it is in fact +a string. + +Add a check on the type, and add a couple to check that 'N' is an integer +in a few places too. + +https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=67d760ab775dae4efe803b5944b0439aa3c0b04a + +From: Ken Sharp +Date: Wed, 14 Nov 2018 09:31:10 +0000 (+0000) +Subject: PS interpreter - add some type checking + +PS interpreter - add some type checking + +These were 'probably' safe anyway, since they mostly treat the objects +as integers without checking, which at least can't result in a crash. + +Nevertheless, we ought to check. + +The return from comparedictkeys could be wrong if one of the keys had +a value which was not an array, it could incorrectly decide the two +were in fact the same. + +https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=548bb434e81dadcc9f71adf891a3ef5bea8e2b4e +--- + +diff -up ghostscript-9.07/psi/zbfont.c.cve-2018-19476 ghostscript-9.07/psi/zbfont.c +--- ghostscript-9.07/psi/zbfont.c.cve-2018-19476 2019-01-14 16:06:09.944218434 +0100 ++++ ghostscript-9.07/psi/zbfont.c 2019-01-14 16:08:36.868448531 +0100 +@@ -618,6 +618,9 @@ sub_font_params(gs_memory_t *mem, const + return_error(e_invalidfont); + if (dict_find_string(op, "OrigFont", &porigfont) <= 0) + porigfont = NULL; ++ if (porigfont != NULL && !r_has_type(porigfont, t_dictionary)) ++ return_error(gs_error_typecheck); ++ + if (pomat!= NULL) { + if (porigfont == NULL || + dict_find_string(porigfont, "FontMatrix", &pmatrix) <= 0 || +@@ -628,8 +631,8 @@ sub_font_params(gs_memory_t *mem, const + /* Use the FontInfo/OrigFontName key preferrentially (created by MS PSCRIPT driver) */ + if ((dict_find_string((porigfont != NULL ? porigfont : op), "FontInfo", &pfontinfo) > 0) && + r_has_type(pfontinfo, t_dictionary) && +- (dict_find_string(pfontinfo, "OrigFontName", &pfontname) > 0)) { +- if ((dict_find_string(pfontinfo, "OrigFontStyle", &pfontstyle) > 0) && ++ (dict_find_string(pfontinfo, "OrigFontName", &pfontname) > 0) && (r_has_type(pfontname, t_name) || r_has_type(pfontname, t_string))) { ++ if ((dict_find_string(pfontinfo, "OrigFontStyle", &pfontstyle) > 0) && (r_has_type(pfontname, t_name) || r_has_type(pfontname, t_string)) && + r_size(pfontstyle) > 0) { + const byte *tmpStr1 = pfontname->value.const_bytes; + const byte *tmpStr2 = pfontstyle->value.const_bytes; +diff -up ghostscript-9.07/psi/zcolor.c.cve-2018-19476 ghostscript-9.07/psi/zcolor.c +--- ghostscript-9.07/psi/zcolor.c.cve-2018-19476 2019-01-14 16:09:23.141891105 +0100 ++++ ghostscript-9.07/psi/zcolor.c 2019-01-14 16:27:03.317052840 +0100 +@@ -2059,7 +2059,12 @@ static int comparedictkey(i_ctx_t * i_ct + if (r_type(tempref1) == t_null) + return 1; + +- return comparearrays(i_ctx_p, tempref1, tempref2); ++ code = comparearrays(i_ctx_p, tempref1, tempref2); ++ ++ if (code > 0) ++ return 1; ++ else ++ return 0; + } + + /* Check that the WhitePoint of a CIE space is valid */ +@@ -5469,6 +5474,9 @@ static int seticcspace(i_ctx_t * i_ctx_p + code = dict_find_string(&ICCdict, "N", &tempref); + if (code < 0) + return code; ++ if (r_type(tempref) != t_integer) ++ return gs_note_error(gs_error_typecheck); ++ + components = tempref->value.intval; + if (components > count_of(range)) + return_error(e_rangecheck); +@@ -5684,6 +5692,8 @@ static int iccalternatespace(i_ctx_t * i + code = dict_find_string(&ICCdict, "N", &tempref); + if (code <= 0) + return code; ++ if (!r_has_type(tempref, t_integer)) ++ return_error(gs_error_typecheck); + + components = tempref->value.intval; + +@@ -5718,6 +5728,9 @@ static int icccomponents(i_ctx_t * i_ctx + return code; + + code = dict_find_string(&ICCdict, "N", &tempref); ++ if (!r_has_type(tempref, t_integer)) ++ return gs_note_error(gs_error_typecheck); ++ + *n = tempref->value.intval; + return 0; + } +@@ -5730,6 +5743,9 @@ static int iccdomain(i_ctx_t * i_ctx_p, + if (code < 0) + return code; + code = dict_find_string(&ICCdict, "N", &tempref); ++ if (!r_has_type(tempref, t_integer)) ++ return gs_note_error(gs_error_typecheck); ++ + components = tempref->value.intval; + code = dict_find_string(&ICCdict, "Range", &tempref); + if (code >= 0 && !r_has_type(tempref, t_null)) { +@@ -5759,6 +5775,8 @@ static int iccrange(i_ctx_t * i_ctx_p, r + if (code < 0) + return code; + code = dict_find_string(&ICCdict, "N", &tempref); ++ if (!r_has_type(tempref, t_integer)) ++ return gs_note_error(gs_error_typecheck); + components = tempref->value.intval; + code = dict_find_string(&ICCdict, "Range", &tempref); + if (code >= 0 && !r_has_type(tempref, t_null)) { +diff -up ghostscript-9.07/psi/zcrd.c.cve-2018-19476 ghostscript-9.07/psi/zcrd.c +--- ghostscript-9.07/psi/zcrd.c.cve-2018-19476 2019-01-14 16:30:53.508230767 +0100 ++++ ghostscript-9.07/psi/zcrd.c 2019-01-14 16:31:42.609628795 +0100 +@@ -222,8 +222,10 @@ zcrd1_params(os_ptr op, gs_cie_render * + ) + return code; + if (dict_find_string(op, "RenderTable", &pRT) > 0) { +- const ref *prte = pRT->value.const_refs; +- ++ const ref *prte; ++ ++ check_read_type(*pRT, t_array); ++ prte = pRT->value.const_refs; + /* Finish unpacking and checking the RenderTable parameter. */ + check_type_only(prte[4], t_integer); + if (!(prte[4].value.intval == 3 || prte[4].value.intval == 4)) +diff -up ghostscript-9.07/psi/zfjpx.c.cve-2018-19476 ghostscript-9.07/psi/zfjpx.c +--- ghostscript-9.07/psi/zfjpx.c.cve-2018-19476 2019-01-14 16:32:09.315301395 +0100 ++++ ghostscript-9.07/psi/zfjpx.c 2019-01-14 16:32:59.902681210 +0100 +@@ -115,6 +115,8 @@ z_jpx_decode(i_ctx_t * i_ctx_p) + dict_find_string(csdict, "N", &nref) > 0) { + if_debug1m('w', imemory, "[w] JPX image has an external %"PRIpsint + " channel colorspace\n", nref->value.intval); ++ if (r_type(nref) != t_integer) ++ return gs_note_error(gs_error_typecheck); + switch (nref->value.intval) { + case 1: state.colorspace = gs_jpx_cs_gray; + break; +diff -up ghostscript-9.07/psi/zfont0.c.cve-2018-19476 ghostscript-9.07/psi/zfont0.c +--- ghostscript-9.07/psi/zfont0.c.cve-2018-19476 2019-01-14 16:34:52.816296934 +0100 ++++ ghostscript-9.07/psi/zfont0.c 2019-01-14 16:36:07.581380337 +0100 +@@ -243,6 +243,9 @@ zbuildfont0(i_ctx_t *i_ctx_p) + array_get(pfont->memory, &fdepvector, i, &fdep); + /* The lookup can't fail, because of the pre-check above. */ + dict_find_string(&fdep, "FID", &pfid); ++ if (!r_has_type(pfid, t_fontID)) ++ return gs_note_error(gs_error_typecheck); ++ + data.FDepVector[i] = r_ptr(pfid, gs_font); + } + pfont->data = data; +diff -up ghostscript-9.07/psi/zfont.c.cve-2018-19476 ghostscript-9.07/psi/zfont.c +--- ghostscript-9.07/psi/zfont.c.cve-2018-19476 2019-01-14 16:33:26.705352619 +0100 ++++ ghostscript-9.07/psi/zfont.c 2019-01-14 16:34:29.104587630 +0100 +@@ -596,6 +596,9 @@ zfont_info(gs_font *font, const gs_point + info->members |= FONT_INFO_FULL_NAME; + if ((members & FONT_INFO_EMBEDDING_RIGHTS) + && (dict_find_string(pfontinfo, "FSType", &pvalue) > 0)) { ++ if (r_type(pvalue) != t_integer) ++ return gs_note_error(gs_error_typecheck); ++ + info->EmbeddingRights = pvalue->value.intval; + info->members |= FONT_INFO_EMBEDDING_RIGHTS; + } +diff -up ghostscript-9.07/psi/zicc.c.cve-2018-19476 ghostscript-9.07/psi/zicc.c +--- ghostscript-9.07/psi/zicc.c.cve-2018-19476 2019-01-14 15:42:17.836379460 +0100 ++++ ghostscript-9.07/psi/zicc.c 2019-01-14 15:48:50.612698290 +0100 +@@ -79,7 +79,7 @@ int seticc(i_ctx_t * i_ctx_p, int ncomps + want to have this buffer. */ + /* Check if we have the /Name entry. This is used to associate with + specs that have enumerated types to indicate sRGB sGray etc */ +- if (dict_find_string(ICCdict, "Name", &pnameval) > 0){ ++ if (dict_find_string(ICCdict, "Name", &pnameval) > 0 && r_has_type(pnameval, t_string)){ + uint size = r_size(pnameval); + char *str = (char *)gs_alloc_bytes(gs_state_memory(igs), size+1, "seticc"); + memcpy(str, (const char *)pnameval->value.bytes, size); +@@ -261,6 +261,8 @@ zset_outputintent(i_ctx_t * i_ctx_p) + code = dict_find_string(op, "N", &pnval); + if (code < 0) + return code; ++ if (r_type(pnval) != t_integer) ++ return gs_note_error(gs_error_typecheck); + ncomps = pnval->value.intval; + + /* verify the DataSource entry. Creat profile from stream */ +diff -up ghostscript-9.07/psi/zimage3.c.cve-2018-19476 ghostscript-9.07/psi/zimage3.c +--- ghostscript-9.07/psi/zimage3.c.cve-2018-19476 2019-01-14 16:36:31.871082554 +0100 ++++ ghostscript-9.07/psi/zimage3.c 2019-01-14 16:37:41.626227376 +0100 +@@ -53,6 +53,8 @@ zimage3(i_ctx_t *i_ctx_p) + dict_find_string(op, "MaskDict", &pMaskDict) <= 0 + ) + return_error(e_rangecheck); ++ check_type(*pDataDict, t_dictionary); ++ check_type(*pMaskDict, t_dictionary); + if ((code = pixel_image_params(i_ctx_p, pDataDict, + (gs_pixel_image_t *)&image, &ip_data, + 12, false, gs_currentcolorspace(igs))) < 0 || +diff -up ghostscript-9.07/psi/ztrans.c.cve-2018-19476 ghostscript-9.07/psi/ztrans.c +--- ghostscript-9.07/psi/ztrans.c.cve-2018-19476 2019-01-14 16:38:14.893819526 +0100 ++++ ghostscript-9.07/psi/ztrans.c 2019-01-14 16:42:22.503788524 +0100 +@@ -362,6 +362,7 @@ zimage3x(i_ctx_t *i_ctx_p) + gs_image3x_t_init(&image, NULL); + if (dict_find_string(op, "DataDict", &pDataDict) <= 0) + return_error(e_rangecheck); ++ check_type(*pDataDict, t_dictionary); + if ((code = pixel_image_params(i_ctx_p, pDataDict, + (gs_pixel_image_t *)&image, &ip_data, + 16, false, gs_currentcolorspace(igs))) < 0 || +@@ -398,6 +399,9 @@ image_params *pip_data, const char *dict + + if (dict_find_string(op, dict_name, &pMaskDict) <= 0) + return 1; ++ if (!r_has_type(pMaskDict, t_dictionary)) ++ return gs_note_error(gs_error_typecheck); ++ + if ((mcode = code = data_image_params(mem, pMaskDict, &pixm->MaskDict, + &ip_mask, false, 1, 16, false, false)) < 0 || + (code = dict_int_param(pMaskDict, "ImageType", 1, 1, 0, &ignored)) < 0 || diff --git a/SOURCES/ghostscript-cve-2018-19477.patch b/SOURCES/ghostscript-cve-2018-19477.patch new file mode 100644 index 0000000..66f8f4b --- /dev/null +++ b/SOURCES/ghostscript-cve-2018-19477.patch @@ -0,0 +1,29 @@ +From: Ken Sharp +Date: Wed, 14 Nov 2018 09:27:00 +0000 (+0000) +Subject: Bug #700168 - add a type check + +Bug #700168 - add a type check + +Bug #700168 "Type confusion in JBIG2Decode" + +The code was assuming that .jbig2globalctx was a structure allocated +by the graphics library, without checking. + +Add a check to see that it is a structure and that its the correct +type of structure. + +https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=ef252e7dc214bcbd9a2539216aab9202848602bb +--- + +diff -up ghostscript-9.07/psi/zfjbig2.c.cve-2018-19477 ghostscript-9.07/psi/zfjbig2.c +--- ghostscript-9.07/psi/zfjbig2.c.cve-2018-19477 2019-01-15 10:36:23.973538520 +0100 ++++ ghostscript-9.07/psi/zfjbig2.c 2019-01-15 10:37:16.897897568 +0100 +@@ -72,6 +72,8 @@ z_jbig2decode(i_ctx_t * i_ctx_p) + if (r_has_type(op, t_dictionary)) { + check_dict_read(*op); + if ( dict_find_string(op, ".jbig2globalctx", &sop) > 0) { ++ if (!r_is_struct(sop) || !r_has_stype(sop, imemory, st_jbig2_global_data_t)) ++ return_error(gs_error_typecheck); + gref = r_ptr(sop, s_jbig2_global_data_t); + s_jbig2decode_set_global_data((stream_state*)&state, gref); + } diff --git a/SOURCES/ghostscript-cve-2019-6116.patch b/SOURCES/ghostscript-cve-2019-6116.patch new file mode 100644 index 0000000..c026749 --- /dev/null +++ b/SOURCES/ghostscript-cve-2019-6116.patch @@ -0,0 +1,895 @@ +commit 30cd347f37bfb293ffdc407397d1023628400b81 +Author: Ken Sharp +Date: Mon Oct 15 13:35:15 2018 +0100 + + font parsing - prevent SEGV in .cffparse + + Bug #699961 "currentcolortransfer procs crash .parsecff" + + zparsecff checked the operand for being an array (and not a packed + array) but the returned procedures from the default currentcolortransfer + are arrays, not packed arrays. This led to the code trying to + dereference a NULL pointer. + + Add a specific check for the 'refs' pointer being NULL before we try + to use it. + + Additionally, make the StartData procedure in the CFF Font Resource + executeonly to prevent pulling the hidden .parsecff operator out and + using it. Finally, extend this to other resource types. + +commit 8e18fcdaa2e2247363c4cc8f851f3096cc5756fa +Author: Chris Liddell +Date: Fri Oct 19 13:14:24 2018 +0100 + + "Hide" a final use of a .force* operator + + There was one use of .forceput remaining that was in a regular procedure + rather than being "hidden" behind an operator. + + In this case, it's buried in the resource machinery, and hard to access (I + would not be confident in claiming it was impossible). This ensures it's + not accessible. + +From d3537a54740d78c5895ec83694a07b3e4f616f61 Mon Sep 17 00:00:00 2001 +From: Chris Liddell +Date: Wed, 5 Dec 2018 12:22:13 +0000 +Subject: [PATCH] Bug700317: Address .force* operators exposure + +Fix logic for an older change: unlike almost every other function in gs, dict_find_string() returns 1 on +success 0 or <0 on failure. The logic for this case was wrong. + +Sanitize op stack for error conditions + +We save the stacks to an array and store the array for the error handler to +access. + +For SAFER, we traverse the array, and deep copy any op arrays (procedures). As +we make these copies, we check for operators that do *not* exist in systemdict, +when we find one, we replace the operator with a name object (of the form +"/--opname--"). + +Any transient procedures that call .force* operators + +(i.e. for conditionals or loops) make them executeonly. + +Harden some uses of .force* operators + +by adding a few immediate evalutions + +CVE-2019-6116 +--- + +diff -up ghostscript-9.07/psi/interp.c.cve-2019-6116 ghostscript-9.07/psi/interp.c +--- ghostscript-9.07/psi/interp.c.cve-2019-6116 2019-01-24 12:20:06.802913354 +0100 ++++ ghostscript-9.07/psi/interp.c 2019-01-24 12:20:06.843912826 +0100 +@@ -692,7 +692,7 @@ again: + * i.e. it's an internal operator we have hidden + */ + code = dict_find_string(systemdict, (const char *)bufptr, &tobj); +- if (code < 0) { ++ if (code <= 0) { + buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-'; + rlen += 4; + bufptr = buf; +@@ -751,6 +751,7 @@ copy_stack(i_ctx_t *i_ctx_p, const ref_s + uint size = ref_stack_count(pstack) - skip; + uint save_space = ialloc_space(idmemory); + int code, i; ++ ref *safety, *safe; + + if (size > 65535) + size = 65535; +@@ -768,6 +769,13 @@ copy_stack(i_ctx_t *i_ctx_p, const ref_s + make_null(&arr->value.refs[i]); + } + } ++ if (pstack == &o_stack && dict_find_string(systemdict, "SAFETY", &safety) > 0 && ++ dict_find_string(safety, "safe", &safe) > 0 && r_has_type(safe, t_boolean) && ++ safe->value.boolval == true) { ++ code = ref_stack_array_sanitize(i_ctx_p, arr, arr); ++ if (code < 0) ++ return code; ++ } + ialloc_set_space(idmemory, save_space); + return code; + } +diff -up ghostscript-9.07/psi/int.mak.cve-2019-6116 ghostscript-9.07/psi/int.mak +--- ghostscript-9.07/psi/int.mak.cve-2019-6116 2019-01-24 12:20:06.824913071 +0100 ++++ ghostscript-9.07/psi/int.mak 2019-01-24 12:20:06.843912826 +0100 +@@ -199,7 +199,7 @@ $(PSOBJ)iparam.$(OBJ) : $(PSSRC)iparam.c + $(PSOBJ)istack.$(OBJ) : $(PSSRC)istack.c $(GH) $(memory__h)\ + $(ierrors_h) $(gsstruct_h) $(gsutil_h)\ + $(ialloc_h) $(istack_h) $(istkparm_h) $(istruct_h) $(iutil_h) $(ivmspace_h)\ +- $(store_h) ++ $(store_h) $(icstate_h) $(iname_h) $(dstack_h) $(idict_h) + $(PSCC) $(PSO_)istack.$(OBJ) $(C_) $(PSSRC)istack.c + + $(PSOBJ)iutil.$(OBJ) : $(PSSRC)iutil.c $(GH) $(math__h) $(memory__h) $(string__h)\ +diff -up ghostscript-9.07/psi/istack.c.cve-2019-6116 ghostscript-9.07/psi/istack.c +--- ghostscript-9.07/psi/istack.c.cve-2019-6116 2013-02-14 08:58:13.000000000 +0100 ++++ ghostscript-9.07/psi/istack.c 2019-01-24 12:20:06.844912813 +0100 +@@ -27,6 +27,10 @@ + #include "iutil.h" + #include "ivmspace.h" /* for local/global test */ + #include "store.h" ++#include "icstate.h" ++#include "iname.h" ++#include "dstack.h" ++#include "idict.h" + + /* Forward references */ + static void init_block(ref_stack_t *pstack, const ref *pblock_array, +@@ -283,6 +287,80 @@ ref_stack_store_check(const ref_stack_t + return 0; + } + ++int ++ref_stack_array_sanitize(i_ctx_t *i_ctx_p, ref *sarr, ref *darr) ++{ ++ int i, code; ++ ref obj, arr2; ++ ref *pobj2; ++ gs_memory_t *mem = (gs_memory_t *)idmemory->current; ++ ++ if (!r_is_array(sarr) || !r_has_type(darr, t_array)) ++ return_error(gs_error_typecheck); ++ ++ for (i = 0; i < r_size(sarr); i++) { ++ code = array_get(mem, sarr, i, &obj); ++ if (code < 0) ++ make_null(&obj); ++ switch(r_type(&obj)) { ++ case t_operator: ++ { ++ int index = op_index(&obj); ++ ++ if (index > 0 && index < op_def_count) { ++ const byte *data = (const byte *)(op_index_def(index)->oname + 1); ++ if (dict_find_string(systemdict, (const char *)data, &pobj2) <= 0) { ++ byte *s = gs_alloc_bytes(mem, strlen((char *)data) + 5, "ref_stack_array_sanitize"); ++ if (s) { ++ s[0] = '\0'; ++ strcpy((char *)s, "--"); ++ strcpy((char *)s + 2, (char *)data); ++ strcpy((char *)s + strlen((char *)data) + 2, "--"); ++ } ++ else { ++ s = (byte *)data; ++ } ++ code = name_ref(imemory, s, strlen((char *)s), &obj, 1); ++ if (code < 0) make_null(&obj); ++ if (s != data) ++ gs_free_object(mem, s, "ref_stack_array_sanitize"); ++ } ++ } ++ else { ++ make_null(&obj); ++ } ++ ref_assign(darr->value.refs + i, &obj); ++ break; ++ } ++ case t_array: ++ case t_shortarray: ++ case t_mixedarray: ++ { ++ int attrs = r_type_attrs(&obj) & (a_write | a_read | a_execute | a_executable); ++ /* We only want to copy executable arrays */ ++ if (attrs & (a_execute | a_executable)) { ++ code = ialloc_ref_array(&arr2, attrs, r_size(&obj), "ref_stack_array_sanitize"); ++ if (code < 0) { ++ make_null(&arr2); ++ } ++ else { ++ code = ref_stack_array_sanitize(i_ctx_p, &obj, &arr2); ++ } ++ ref_assign(darr->value.refs + i, &arr2); ++ } ++ else { ++ ref_assign(darr->value.refs + i, &obj); ++ } ++ break; ++ } ++ default: ++ ref_assign(darr->value.refs + i, &obj); ++ } ++ } ++ return 0; ++} ++ ++ + /* + * Store the top 'count' elements of a stack, starting 'skip' elements below + * the top, into an array, with or without store/undo checking. age=-1 for +diff -up ghostscript-9.07/psi/istack.h.cve-2019-6116 ghostscript-9.07/psi/istack.h +--- ghostscript-9.07/psi/istack.h.cve-2019-6116 2013-02-14 08:58:13.000000000 +0100 ++++ ghostscript-9.07/psi/istack.h 2019-01-24 12:20:06.844912813 +0100 +@@ -129,6 +129,9 @@ int ref_stack_store(const ref_stack_t *p + uint skip, int age, bool check, + gs_dual_memory_t *idmem, client_name_t cname); + ++int ++ref_stack_array_sanitize(i_ctx_t *i_ctx_p, ref *sarr, ref *darr); ++ + /* + * Pop the top N elements off a stack. + * The number must not exceed the number of elements in use. +diff -up ghostscript-9.07/psi/zfont2.c.cve-2019-6116 ghostscript-9.07/psi/zfont2.c +--- ghostscript-9.07/psi/zfont2.c.cve-2019-6116 2019-01-24 12:20:06.601915943 +0100 ++++ ghostscript-9.07/psi/zfont2.c 2019-01-24 12:20:06.844912813 +0100 +@@ -2718,9 +2718,13 @@ zparsecff(i_ctx_t *i_ctx_p) + ref blk_wrap[1]; + + check_read(*op); ++ + if (r_has_type(op, t_array)) { /* no packedarrays */ + int i, blk_sz, blk_cnt; + ++ if (op->value.refs == NULL) ++ return_error(gs_error_typecheck); ++ + data.blk_ref = op->value.refs; + blk_cnt = r_size(op); + blk_sz = r_size(data.blk_ref); +diff -up ghostscript-9.07/Resource/Init/gs_cff.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_cff.ps +--- ghostscript-9.07/Resource/Init/gs_cff.ps.cve-2019-6116 2013-02-14 08:58:16.000000000 +0100 ++++ ghostscript-9.07/Resource/Init/gs_cff.ps 2019-01-24 12:20:06.845912801 +0100 +@@ -719,7 +719,7 @@ dup % Format 2 + % ordinary CFF font. + /StartData { % StartData - + currentfile exch subfilefilter //false //false ReadData pop +-} bind def ++} bind executeonly def + /ReadData { % ReadData + % Initialize. + +@@ -860,7 +860,7 @@ systemdict /OLDCFF known { + end % FontSetInit ProcSet + /FontSet defineresource + +-} bind def ++} bind executeonly def + + % ---------------- Resource category definition ---------------- % + +diff -up ghostscript-9.07/Resource/Init/gs_cidcm.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_cidcm.ps +--- ghostscript-9.07/Resource/Init/gs_cidcm.ps.cve-2019-6116 2013-02-14 08:58:16.000000000 +0100 ++++ ghostscript-9.07/Resource/Init/gs_cidcm.ps 2019-01-24 12:20:06.845912801 +0100 +@@ -327,7 +327,7 @@ currentdict end def + //FindResource exec + } ifelse + } ifelse +-} bind def ++} bind executeonly def + + /ResourceStatus { % ResourceStatus true + % ResourceStatus false +@@ -359,7 +359,7 @@ currentdict end def + //false + } ifelse + } ifelse +-} bind def ++} bind executeonly def + + /ResourceForAll { %