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 <chris.liddell@artifex.com> +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 <chris.liddell@artifex.com> +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 <ken.sharp@artifex.com> +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 <ken.sharp@artifex.com> +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 <ken.sharp@artifex.com> +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 <ken.sharp@artifex.com> +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 <chris.liddell@artifex.com> +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 <chris.liddell@artifex.com> +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 { % <resname> <nbytes> StartData - + currentfile exch subfilefilter //false //false ReadData pop +-} bind def ++} bind executeonly def + /ReadData { % <resname> <file> <forceresname> <forcecid> ReadData <fontset> + % 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 { % <InstName> ResourceStatus <nStatus> <nSize> true + % <InstName> ResourceStatus false +@@ -359,7 +359,7 @@ currentdict end def + //false + } ifelse + } ifelse +-} bind def ++} bind executeonly def + + /ResourceForAll { % <template> <proc> <scratch> ResourceForAll - + +@@ -440,7 +440,7 @@ currentdict end def + + % Make the enumerator and apply it : + /MappedCategoryRedefiner /ProcSet findresource /MakeResourceEnumerator get exec exec +-} bind def ++} bind executeonly def + + currentdict end /Font exch /Category defineresource pop + end +diff -up ghostscript-9.07/Resource/Init/gs_ciddc.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_ciddc.ps +--- ghostscript-9.07/Resource/Init/gs_ciddc.ps.cve-2019-6116 2013-02-14 08:58:16.000000000 +0100 ++++ ghostscript-9.07/Resource/Init/gs_ciddc.ps 2019-01-24 12:20:06.845912801 +0100 +@@ -202,7 +202,7 @@ begin + exch pop begin % + .GetCIDDecoding + end +- } bind def ++ } bind executeonly def + + /FindResource % <name> FindResource <dict> + { currentglobal exch % bGlobal /InstName +@@ -210,7 +210,7 @@ begin + dup //.MakeInstance exec % bGlobal /InstName <Inst> + DefineResource % bGlobal <Inst> + exch setglobal % <Inst> +- } bind def ++ } bind executeonly def + + currentdict end + /CIDDecoding exch /Category defineresource pop +diff -up ghostscript-9.07/Resource/Init/gs_cmap.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_cmap.ps +--- ghostscript-9.07/Resource/Init/gs_cmap.ps.cve-2019-6116 2013-02-14 08:58:16.000000000 +0100 ++++ ghostscript-9.07/Resource/Init/gs_cmap.ps 2019-01-24 12:20:06.845912801 +0100 +@@ -535,7 +535,7 @@ dup /DefineResource { + } if + dup /CodeMap .knownget { //null eq { .buildcmap } if } if + /Generic /Category findresource /DefineResource get exec +-} bind put ++} bind executeonly put + /Category defineresource pop + % We might have loaded CID font support already. + /CIDInit /ProcSet 2 copy { findresource } .internalstopped +diff -up ghostscript-9.07/Resource/Init/gs_diskn.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_diskn.ps +--- ghostscript-9.07/Resource/Init/gs_diskn.ps.cve-2019-6116 2019-01-24 12:20:06.813913213 +0100 ++++ ghostscript-9.07/Resource/Init/gs_diskn.ps 2019-01-24 12:20:06.845912801 +0100 +@@ -51,7 +51,7 @@ systemdict begin + mark 5 1 roll ] mark exch { { } forall } forall ] + //systemdict /.searchabledevs 2 index .forceput + exch .setglobal +- } ++ } executeonly + if + } .bind executeonly odef % must be bound and hidden for .forceput + +diff -up ghostscript-9.07/Resource/Init/gs_dps1.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_dps1.ps +--- ghostscript-9.07/Resource/Init/gs_dps1.ps.cve-2019-6116 2019-01-24 12:20:06.798913406 +0100 ++++ ghostscript-9.07/Resource/Init/gs_dps1.ps 2019-01-24 12:20:06.846912788 +0100 +@@ -75,18 +75,18 @@ level2dict begin + } odef + % undefinefont has to take local/global VM into account. + /undefinefont % <fontname> undefinefont - +- { .FontDirectory 1 .argindex .forceundef % FontDirectory is readonly ++ { //.FontDirectory 1 .argindex .forceundef % FontDirectory is readonly + .currentglobal + { % Current mode is global; delete from local directory too. + //systemdict /LocalFontDirectory .knownget +- { 1 index .forceundef } % LocalFontDirectory is readonly ++ { 1 index .forceundef } executeonly % LocalFontDirectory is readonly + if + } + { % Current mode is local; if there was a shadowed global + % definition, copy it into the local directory. + //systemdict /SharedFontDirectory .knownget + { 1 index .knownget +- { .FontDirectory 2 index 3 -1 roll { put } //superexec } % readonly ++ { //.FontDirectory 2 index 3 -1 roll { put } //superexec } % readonly + if + } + if +@@ -127,7 +127,7 @@ level2dict begin + } + ifelse + } forall +- pop counttomark 2 idiv { .forceundef } repeat pop % readonly ++ pop counttomark 2 idiv { .forceundef } executeonly repeat pop % readonly + } + if + //SharedFontDirectory exch .forcecopynew pop +diff -up ghostscript-9.07/Resource/Init/gs_dps.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_dps.ps +--- ghostscript-9.07/Resource/Init/gs_dps.ps.cve-2019-6116 2019-01-24 12:20:06.813913213 +0100 ++++ ghostscript-9.07/Resource/Init/gs_dps.ps 2019-01-24 12:20:06.846912788 +0100 +@@ -118,7 +118,7 @@ + .dicttomark readonly /localdicts exch put + % localdicts is now defined in userdict. + % Copy the definitions into systemdict. +- localdicts { .forcedef } forall ++ localdicts { .forcedef } executeonly forall + % Set the user parameters. + userparams readonly .setuserparams + % Establish the initial gstate(s). +diff -up ghostscript-9.07/Resource/Init/gs_fntem.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_fntem.ps +--- ghostscript-9.07/Resource/Init/gs_fntem.ps.cve-2019-6116 2019-01-24 12:20:06.807913290 +0100 ++++ ghostscript-9.07/Resource/Init/gs_fntem.ps 2019-01-24 12:20:06.846912788 +0100 +@@ -425,12 +425,12 @@ currentdict end def + .forceput % FontInfo can be read-only. + pop % bool <font> + exit +- } if ++ } executeonly if + dup /FontInfo get % bool <font> <FI> + /GlyphNames2Unicode /Unicode /Decoding findresource + .forceput % FontInfo can be read-only. + exit +- } loop ++ } executeonly loop + exch setglobal + } .bind executeonly odef % must be bound and hidden for .forceput + +diff -up ghostscript-9.07/Resource/Init/gs_fonts.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_fonts.ps +--- ghostscript-9.07/Resource/Init/gs_fonts.ps.cve-2019-6116 2019-01-24 12:20:06.814913200 +0100 ++++ ghostscript-9.07/Resource/Init/gs_fonts.ps 2019-01-24 12:20:06.846912788 +0100 +@@ -505,7 +505,7 @@ buildfontdict 3 /.buildfont3 cvx put + if + } + if +- dup .FontDirectory 4 -2 roll { .growput } //superexec % readonly ++ dup //.FontDirectory 4 -2 roll { .growput } //superexec % readonly + % If the font originated as a resource, register it. + currentfile .currentresourcefile eq { dup .registerfont } if + readonly +@@ -927,7 +927,7 @@ $error /SubstituteFont { } put + % Try to find a font using only the present contents of Fontmap. + /.tryfindfont { % <fontname> .tryfindfont <font> true + % <fontname> .tryfindfont false +- .FontDirectory 1 index .fontknownget ++ //.FontDirectory 1 index .fontknownget + { % Already loaded + exch pop //true + } +@@ -948,7 +948,7 @@ $error /SubstituteFont { } put + { % Font with a procedural definition + exec % The procedure will load the font. + % Check to make sure this really happened. +- .FontDirectory 1 index .knownget ++ //.FontDirectory 1 index .knownget + { exch pop //true exit } + if + } +@@ -980,11 +980,11 @@ $error /SubstituteFont { } put + { 2 index gcheck currentglobal + 2 copy eq { + pop pop .forceput +- } { ++ } executeonly { + 5 1 roll setglobal + dup length string copy + .forceput setglobal +- } ifelse ++ } executeonly ifelse + } .bind executeonly odef % must be bound and hidden for .forceput + + % Attempt to load a font from a file. +@@ -1060,11 +1060,11 @@ $error /SubstituteFont { } put + % because it's different depending on language level. + .currentglobal exch /.setglobal .systemvar exec + % Remove the fake definition, if any. +- .FontDirectory 3 index .forceundef % readonly +- 1 index (r) file .loadfont .FontDirectory exch ++ //.FontDirectory 3 index .forceundef % readonly ++ 1 index (r) file .loadfont //.FontDirectory exch + /.setglobal .systemvar exec +- } +- { .loadfont .FontDirectory ++ } executeonly ++ { .loadfont //.FontDirectory + } + ifelse + % Stack: fontname fontfilename fontdirectory +@@ -1084,7 +1084,7 @@ $error /SubstituteFont { } put + dup 3 index .fontknownget + { dup /PathLoad 4 index //.putgstringcopy + 4 1 roll pop pop pop //true exit +- } if ++ } executeonly if + + % Maybe the file had a different FontName. + % See if we can get a FontName from the file, and if so, +@@ -1108,9 +1108,9 @@ $error /SubstituteFont { } put + ifelse % Stack: origfontname fontdict + exch pop //true exit + % Stack: fontdict +- } ++ } executeonly + if pop % Stack: origfontname fontdirectory path +- } ++ } executeonly + if pop pop % Stack: origfontname + + % The font definitely did not load correctly. +@@ -1146,10 +1146,10 @@ currentdict /.putgstringcopy .forceundef + (gs_fonts FAKEFONTS) VMDEBUG + Fontmap { + pop dup type /stringtype eq { cvn } if +- .FontDirectory 1 index known not { ++ //.FontDirectory 1 index known not { + 2 dict dup /FontName 3 index put + dup /FontType 1 put +- .FontDirectory 3 1 roll { put } //superexec % readonly ++ //.FontDirectory 3 1 roll { put } //superexec % readonly + } { + pop + } ifelse +diff -up ghostscript-9.07/Resource/Init/gs_init.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_init.ps +--- ghostscript-9.07/Resource/Init/gs_init.ps.cve-2019-6116 2019-01-24 12:20:06.826913045 +0100 ++++ ghostscript-9.07/Resource/Init/gs_init.ps 2019-01-24 12:20:06.846912788 +0100 +@@ -1157,8 +1157,8 @@ errordict /unknownerror .undef + //.SAFERERRORLIST + {dup errordict exch get 2 index 3 1 roll put} forall + noaccess pop +- systemdict /.setsafeerrors .forceundef +- systemdict /.SAFERERRORLIST .forceundef ++ //systemdict /.setsafeerrors .forceundef ++ //systemdict /.SAFERERRORLIST .forceundef + } bind executeonly odef + + SAFERERRORS {.setsafererrors} if +@@ -2080,7 +2080,7 @@ readonly def + /LockFilePermissions //true + >> setuserparams + } +- systemdict /getenv {pop //false} .forceput ++ //systemdict /getenv {pop //false} .forceput + if + % setpagedevice has the side effect of clearing the page, but + % we will just document that. Using setpagedevice keeps the device +@@ -2287,7 +2287,7 @@ SAFER { .setsafe } if + % Update the copy of the user parameters. + mark .currentuserparams counttomark 2 idiv { + userparams 3 1 roll .forceput % userparams is read-only +- } repeat pop ++ } executeonly repeat pop + % Turn on idiom recognition, if available. + currentuserparams /IdiomRecognition known { + /IdiomRecognition //true .definepsuserparam +@@ -2306,7 +2306,7 @@ SAFER { .setsafe } if + % Remove real system params from pssystemparams. + mark .currentsystemparams counttomark 2 idiv { + pop pssystemparams exch .forceundef +- } repeat pop ++ } executeonly repeat pop + } if + + % Set up AlignToPixels : +diff -up ghostscript-9.07/Resource/Init/gs_lev2.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_lev2.ps +--- ghostscript-9.07/Resource/Init/gs_lev2.ps.cve-2019-6116 2019-01-24 12:20:06.808913277 +0100 ++++ ghostscript-9.07/Resource/Init/gs_lev2.ps 2019-01-24 12:20:06.854912684 +0100 +@@ -154,7 +154,8 @@ end + % protect top level of parameters that we copied + dup type dup /arraytype eq exch /stringtype eq or { readonly } if + /userparams .systemvar 3 1 roll .forceput % userparams is read-only +- } { ++ } executeonly ++ { + pop pop + } ifelse + } forall +@@ -223,7 +224,7 @@ end + % protect top level parameters that we copied + dup type dup /arraytype eq exch /stringtype eq or { readonly } if + //pssystemparams 3 1 roll .forceput % pssystemparams is read-only +- } ++ } executeonly + { pop pop + } + ifelse +@@ -911,7 +912,7 @@ mark + dup /PaintProc get + 1 index /Implementation known not { + 1 index dup /Implementation //null .forceput readonly pop +- } if ++ } executeonly if + exec + } .bind odef % must bind .forceput + +diff -up ghostscript-9.07/Resource/Init/gs_pdfwr.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_pdfwr.ps +--- ghostscript-9.07/Resource/Init/gs_pdfwr.ps.cve-2019-6116 2019-01-24 12:20:06.808913277 +0100 ++++ ghostscript-9.07/Resource/Init/gs_pdfwr.ps 2019-01-24 12:20:06.855912672 +0100 +@@ -541,7 +541,7 @@ currentdict /.pdfmarkparams .undef + resourcestatus + } ifelse + } bind .makeoperator .forceput +- } if ++ } executeonly if + pop + } if + } { +diff -up ghostscript-9.07/Resource/Init/gs_res.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_res.ps +--- ghostscript-9.07/Resource/Init/gs_res.ps.cve-2019-6116 2013-02-14 08:58:16.000000000 +0100 ++++ ghostscript-9.07/Resource/Init/gs_res.ps 2019-01-24 12:20:06.857912646 +0100 +@@ -155,10 +155,10 @@ setglobal + } { + /defineresource cvx /typecheck signaloperror + } ifelse +-} bind def ++} bind executeonly odef + /FindResource % (redefined below) + { .Instances exch get 0 get +- } bind def ++ } bind executeonly def + + % Additional entries + +@@ -210,7 +210,7 @@ def + /findresource .systemvar /typecheck signalerror + } if + /findresource cvx //.findresource .errorexec +-} odef ++} bind executeonly odef + + /defineresource { % <key> <instance> <category> defineresource <instance> + 2 .argindex 2 index 2 index % catch stackunderflow +@@ -226,7 +226,7 @@ def + /DefineResource .resourceexec + 4 1 roll pop pop pop + } .errorexec +-} bind odef ++} bind executeonly odef + % We must prevent resourceforall from automatically restoring the stacks, + % because we don't want the stacks restored if proc causes an error or + % executes a 'stop'. On the other hand, resourceforall is defined in the +@@ -240,10 +240,10 @@ def + % Stack: <template> <proc> <scratch> <category> proc + exch pop % pop the category + exec end +-} bind def ++} bind executeonly def + /resourceforall { % <template> <proc> <scratch> <category> resourceforall1 - + //resourceforall1 exec % see above +-} bind odef ++} bind executeonly odef + /resourcestatus { % <key> <category> resourcestatus <status> <size> true + % <key> <category> resourcestatus false + { +@@ -259,7 +259,7 @@ def + % for error reporting. CET 23-26 + /resourcestatus cvx $error /errorname get signalerror + } if +-} bind odef ++} bind executeonly odef + /undefineresource { % <key> <category> undefineresource - + 0 .argindex type /nametype ne { + /undefinedresource cvx /typecheck signaloperror +@@ -272,7 +272,7 @@ def + % here but uses operator for the errors above. CET 23-33 + /undefineresource cvx $error /errorname get signalerror + } if +-} bind odef ++} bind executeonly odef + + % Define the system parameters used for the Generic implementation of + % ResourceFileName. +@@ -412,7 +412,7 @@ status { + } ifelse + } bind def + +-/DefineResource { ++/DefineResource dup { + .CheckResource + { dup [ exch 0 -1 ] + % Stack: key value instance +@@ -424,7 +424,7 @@ status { + % As noted above, Category dictionaries are read-only, + % so we have to use .forcedef here. + /.Instances 1 index .forcedef % Category dict is read-only +- } if ++ } executeonly if + } + { .LocalInstances dup //.emptydict eq + { pop 3 dict localinstancedict Category 2 index put +@@ -441,7 +441,7 @@ status { + { /defineresource cvx /typecheck signaloperror + } + ifelse +-} .bind executeonly % executeonly to prevent access to .forcedef ++} .bind executeonly .makeoperator % executeonly to prevent access to .forcedef + /UndefineResource + { { dup 2 index .knownget + { dup 1 get 1 ge +@@ -457,7 +457,7 @@ status { + { 2 copy .Instances exch exec + } + if .LocalInstances exch exec +- } bind ++ } bind executeonly + % Because of some badly designed code in Adobe's CID font downloader that + % makes findresource and resourcestatus deliberately inconsistent with each + % other, the default FindResource must not call ResourceStatus if there is +@@ -483,7 +483,7 @@ status { + /findresource cvx .undefinedresource + } ifelse + } ifelse +-} bind ++} bind executeonly + % Because of some badly designed code in Adobe's CID font downloader, the + % definition of ResourceStatus for Generic and Font must be the same (!). + % We patch around this by using an intermediate .ResourceFileStatus procedure. +@@ -493,10 +493,10 @@ status { + } { + .ResourceFileStatus + } ifelse +-} bind ++} bind executeonly + /.ResourceFileStatus { + .ResourceFile { closefile 2 -1 //true } { pop //false } ifelse +-} bind ++} bind executeonly + /ResourceForAll { + % Construct a new procedure to hold the arguments. + % All objects constructed here must be in local VM to avoid +@@ -554,7 +554,7 @@ status { + 3 2 roll pop % args + { forall } 0 get + currentdict end 2 .execn begin +-} bind ++} bind executeonly + + /ResourceFileName { % /in (scr) --> (p/c/n) + exch //.rfnstring cvs % (scr) (n) +@@ -577,7 +577,7 @@ status { + } ifelse + } ifelse + exch copy % (p/c/n) +-} bind ++} bind executeonly + + % Additional entries + +@@ -743,17 +743,17 @@ counttomark 2 idiv + ifelse + } + ifelse +- } bind ++ } bind executeonly + /UndefineResource +- { /undefineresource cvx /invalidaccess signaloperror } bind ++ { /undefineresource cvx /invalidaccess signaloperror } bind executeonly + /FindResource + { .Instances 1 index .knownget + { exch pop } + { /findresource cvx .undefinedresource } + ifelse +- } bind ++ } bind executeonly + /ResourceStatus +- { .Instances exch known { 0 0 //true } { //false } ifelse } bind ++ { .Instances exch known { 0 0 //true } { //false } ifelse } bind executeonly + /ResourceForAll + /Generic .findcategory /ResourceForAll load end + +@@ -836,7 +836,7 @@ userdict /.localcsdefaults //false put + 1 index .definedefaultcs + currentglobal not { .userdict /.localcsdefaults //true put } if + } if +-} bind ++} bind executeonly + + /UndefineResource { + dup /Generic /Category findresource /UndefineResource get exec +@@ -859,7 +859,7 @@ userdict /.localcsdefaults //false put + } { + pop + } ifelse +-} bind ++} bind executeonly + + .definecategory % ColorSpace + +@@ -889,7 +889,7 @@ userdict /.localcsdefaults //false put + { exch copy exch pop } + { /Generic /Category findresource /ResourceFileName get exec } + ifelse +- } bind ++ } bind executeonly + + .definecategory % Encoding + +@@ -945,11 +945,11 @@ userdict /.localcsdefaults //false put + /DefineResource + { 2 copy //definefont exch pop + /Generic /Category findresource /DefineResource get exec +- } bind ++ } bind executeonly + /UndefineResource + { dup //undefinefont + /Generic /Category findresource /UndefineResource get exec +- } bind ++ } bind executeonly + /FindResource { + dup .getvminstance { + exch pop 0 get +@@ -960,14 +960,14 @@ userdict /.localcsdefaults //false put + .loadfontresource + } ifelse + } ifelse +-} bind ++} bind executeonly + /ResourceForAll { + { .scannextfontdir not { exit } if } loop + /Generic /Category findresource /ResourceForAll get exec +-} bind ++} bind executeonly + /.ResourceFileStatus { + .fontstatus { pop 2 -1 //true } { pop //false } ifelse +-} bind ++} bind executeonly + + /.loadfontresource { + dup .vmused exch +@@ -1017,20 +1017,20 @@ end + { /Font defineresource } stopped { + /definefont cvx $error /errorname get signalerror + } if +-} bind odef ++} bind executeonly odef + /undefinefont { + /Font undefineresource +-} bind odef ++} bind executeonly odef + % The Red Book requires that findfont be a procedure, not an operator, + % but it still needs to restore the stacks reliably if it fails. + /.findfontop { + { /Font findresource } stopped { + pop /findfont $error /errorname get signalerror + } if +-} bind odef ++} bind executeonly odef + /findfont { + .findfontop +-} bind def % Must be a procedure, not an operator ++} bind executeonly def % Must be a procedure, not an operator + + % Remove initialization utilities. + currentdict /.definecategory .undef +diff -up ghostscript-9.07/Resource/Init/gs_setpd.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/gs_setpd.ps +--- ghostscript-9.07/Resource/Init/gs_setpd.ps.cve-2019-6116 2019-01-24 12:20:06.815913187 +0100 ++++ ghostscript-9.07/Resource/Init/gs_setpd.ps 2019-01-24 12:20:06.856912659 +0100 +@@ -570,7 +570,7 @@ NOMEDIAATTRS { + SETPDDEBUG { (Rolling back.) = pstack flush } if + 3 index 2 index 3 -1 roll .forceput + 4 index 1 index .knownget +- { 4 index 3 1 roll .forceput } ++ { 4 index 3 1 roll .forceput } executeonly + { 3 index exch .undef } + ifelse + } bind executeonly odef +diff -up ghostscript-9.07/Resource/Init/pdf_base.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/pdf_base.ps +--- ghostscript-9.07/Resource/Init/pdf_base.ps.cve-2019-6116 2019-01-24 12:20:06.809913264 +0100 ++++ ghostscript-9.07/Resource/Init/pdf_base.ps 2019-01-24 12:20:06.856912659 +0100 +@@ -125,26 +125,26 @@ currentdict /num-chars-dict .undef + + /.pdfexectoken { % <count> <opdict> <exectoken> .pdfexectoken ? + PDFDEBUG { +- pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } if ++ pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } executeonly if + PDFSTEP { + pdfdict /PDFtokencount 2 copy .knownget { 1 add } { 1 } ifelse .forceput + PDFSTEPcount 1 gt { + pdfdict /PDFSTEPcount PDFSTEPcount 1 sub .forceput +- } { ++ } executeonly { + dup ==only + ( step # ) print PDFtokencount =only + ( ? ) print flush 1 //false .outputpage + (%stdin) (r) file 255 string readline { + token { + exch pop pdfdict /PDFSTEPcount 3 -1 roll .forceput +- } { ++ } executeonly { + pdfdict /PDFSTEPcount 1 .forceput +- } ifelse % token ++ } executeonly ifelse % token + } { + pop /PDFSTEP //false def % EOF on stdin + } ifelse % readline + } ifelse % PDFSTEPcount > 1 +- } { ++ } executeonly { + dup ==only () = flush + } ifelse % PDFSTEP + } if % PDFDEBUG +diff -up ghostscript-9.07/Resource/Init/pdf_font.ps.cve-2019-6116 ghostscript-9.07/Resource/Init/pdf_font.ps +--- ghostscript-9.07/Resource/Init/pdf_font.ps.cve-2019-6116 2019-01-24 12:20:06.810913251 +0100 ++++ ghostscript-9.07/Resource/Init/pdf_font.ps 2019-01-24 12:20:06.857912646 +0100 +@@ -614,7 +614,7 @@ currentdict end readonly def + currentglobal 2 index dup gcheck setglobal + /FontInfo 5 dict dup 5 1 roll .forceput + setglobal +- } if ++ } executeonly if + dup /GlyphNames2Unicode .knownget not { + //true % No existing G2U, make one + } { +@@ -628,7 +628,7 @@ currentdict end readonly def + currentglobal exch dup gcheck setglobal + dup /GlyphNames2Unicode 100 dict dup 4 1 roll .forceput + 3 2 roll setglobal +- } if % font-res font-dict encoding|null font-info g2u ++ } executeonly if % font-res font-dict encoding|null font-info g2u + exch pop exch % font-res font-dict g2u encoding|null + userdict /.lastToUnicode get % font-res font-dict g2u Encoding|null CMap + .convert_ToUnicode-into-g2u % font-res font-dict +@@ -1757,7 +1757,7 @@ currentdict /CMap_read_dict undef + /CIDFallBack /CIDFont findresource + } if + exit +- } if ++ } executeonly if + } if + } if + diff --git a/SOURCES/ghostscript-pdf2ps-reports-error-when-reading-stdin.patch b/SOURCES/ghostscript-pdf2ps-reports-error-when-reading-stdin.patch new file mode 100644 index 0000000..30b915d --- /dev/null +++ b/SOURCES/ghostscript-pdf2ps-reports-error-when-reading-stdin.patch @@ -0,0 +1,208 @@ +From: Chris Liddell <chris.liddell@artifex.com> +Date: Sat, 1 Sep 2018 16:50:05 +0000 (+0100) +Subject: Bug 699658(related): Move recording of temp file names into C + +Bug 699658(related): Move recording of temp file names into C + +When we successfully create a temporary file from Postscript, either doing so +when SAFER is not in force, or when SAFER is in force, and creating it in +a write permitted directory, we record the file name so we can later delete +the file, even is SAFER has been engaged, or if the PermitWriting list has +changed to no longer the directory in question. + +Previously the recording of the name was done in Postscript, even though the +checking was done in C. + +This moves the recording of the names to C, meaning we can remove the Postscript +redefinitions of .tempfile and deletfile, and make the dictionary in question +noaccess. + +Also, tidy up the adding of the temporary file directory to the list of +permitted directories, and include the list in all of the categories +(PermitFileWriting, PermitFileReading and PermitFileControl) - it was only +previously adding to writing. + +https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=0704d18b10314d701a522ad6c16718e0b8e199b7 +--- + +diff -up ghostscript-9.07/psi/int.mak.bz1661210 ghostscript-9.07/psi/int.mak +--- ghostscript-9.07/psi/int.mak.bz1661210 2018-12-20 17:38:21.683312408 +0100 ++++ ghostscript-9.07/psi/int.mak 2018-12-20 17:38:40.583083097 +0100 +@@ -330,7 +330,7 @@ $(PSOBJ)zfile.$(OBJ) : $(PSSRC)zfile.c $ + $(memory__h) $(string__h) $(unistd__h) $(stat__h) $(gp_h) $(gpmisc_h)\ + $(gscdefs_h) $(gsfname_h) $(gsstruct_h) $(gsutil_h) $(gxalloc_h) $(gxiodev_h)\ + $(dstack_h) $(estack_h) $(files_h)\ +- $(ialloc_h) $(idict_h) $(ilevel_h) $(iname_h) $(iutil_h)\ ++ $(ialloc_h) $(idict_h) $(iddict_h) $(ilevel_h) $(iname_h) $(iutil_h)\ + $(isave_h) $(main_h) $(sfilter_h) $(stream_h) $(strimpl_h) $(store_h)\ + $(zfile_h) + $(PSCC) $(PSO_)zfile.$(OBJ) $(C_) $(PSSRC)zfile.c +diff -up ghostscript-9.07/psi/zfile.c.bz1661210 ghostscript-9.07/psi/zfile.c +--- ghostscript-9.07/psi/zfile.c.bz1661210 2018-12-20 17:39:09.975726450 +0100 ++++ ghostscript-9.07/psi/zfile.c 2018-12-20 17:44:50.698592208 +0100 +@@ -35,6 +35,7 @@ + #include "iname.h" + #include "isave.h" /* for restore */ + #include "idict.h" ++#include "iddict.h" + #include "iutil.h" + #include "stream.h" + #include "strimpl.h" +@@ -290,6 +291,28 @@ file_is_tempfile(i_ctx_t *i_ctx_p, const + return true; + } + ++static int ++record_file_is_tempfile(i_ctx_t *i_ctx_p, const uchar *fname, int len, bool add) ++{ ++ ref *SAFETY; ++ ref *tempfiles; ++ ref kname, bref; ++ int code = 0; ++ ++ if (dict_find_string(systemdict, "SAFETY", &SAFETY) <= 0 || ++ dict_find_string(SAFETY, "tempfiles", &tempfiles) <= 0) { ++ return 0; ++ } ++ if ((code = name_ref(imemory, fname, len, &kname, 1)) < 0) { ++ return code; ++ } ++ make_bool(&bref, true); ++ if (add) ++ return idict_put(tempfiles, &kname, &bref); ++ else ++ return idict_undef(tempfiles, &kname); ++} ++ + /* ------ Level 2 extensions ------ */ + + /* <string> deletefile - */ +@@ -299,17 +322,22 @@ zdeletefile(i_ctx_t *i_ctx_p) + os_ptr op = osp; + gs_parsed_file_name_t pname; + int code = parse_real_file_name(op, &pname, imemory, "deletefile"); ++ bool is_temp = false; + + if (code < 0) + return code; + if (pname.iodev == iodev_default(imemory)) { + if ((code = check_file_permissions(i_ctx_p, pname.fname, pname.len, + pname.iodev, "PermitFileControl")) < 0 && +- !file_is_tempfile(i_ctx_p, op->value.bytes, r_size(op))) { ++ !(is_temp = file_is_tempfile(i_ctx_p, op->value.bytes, r_size(op)))) { + return code; + } + } + code = (*pname.iodev->procs.delete_file)(pname.iodev, pname.fname); ++ ++ if (code >= 0 && is_temp) ++ code = record_file_is_tempfile(i_ctx_p, (unsigned char *)pname.fname, strlen(pname.fname), false); ++ + gs_free_file_name(&pname, "deletefile"); + if (code < 0) + return code; +@@ -757,6 +785,7 @@ ztempfile(i_ctx_t *i_ctx_p) + } + make_string(op - 1, a_readonly | icurrent_space, fnlen, sbody); + make_stream_file(op, s, fmode); ++ code = record_file_is_tempfile(i_ctx_p, (unsigned char *)fname, fnlen, true); + return code; + } + +diff -up ghostscript-9.07/Resource/Init/gs_init.ps.bz1661210 ghostscript-9.07/Resource/Init/gs_init.ps +--- ghostscript-9.07/Resource/Init/gs_init.ps.bz1661210 2018-12-20 17:33:51.469591104 +0100 ++++ ghostscript-9.07/Resource/Init/gs_init.ps 2018-12-20 17:35:36.694314341 +0100 +@@ -2030,15 +2030,30 @@ systemdict /EPSBoundingBoxInit known { E + .currentglobal //true .setglobal + /SAFETY 2 dict + dup /safe //false put +- dup /tempfiles 10 dict readonly put ++ dup /tempfiles 10 dict noaccess put + readonly def + .setglobal + ++/tempfilepaths ++[ ++ (TMPDIR) getenv not ++ { ++ (TEMP) getenv not ++ { ++ (TMP) getenv not ++ { ++ (/temp) (/tmp) ++ } if ++ } if ++ } if ++] def ++ + /.locksafe { + SAFETY /safe get not { + << + /PermitFileReading [ + currentuserparams /PermitFileReading get aload pop ++ //tempfilepaths aload pop + /FONTPATH .systemvar (*) .generate_dir_list_templates + % Library files : + /LIBPATH .systemvar (*) .generate_dir_list_templates +@@ -2056,16 +2071,11 @@ readonly def + ] + /PermitFileWriting [ + currentuserparams /PermitFileWriting get aload pop +- (TMPDIR) getenv not +- { +- (TEMP) getenv not +- { +- (TMP) getenv not +- { +- (/temp) (/tmp) +- } if +- } if +- } if ++ //tempfilepaths aload pop ++ ] ++ /PermitFileControl [ ++ currentuserparams /PermitFileControl get aload pop ++ //tempfilepaths aload pop + ] + /LockFilePermissions //true + >> setuserparams +@@ -2082,6 +2092,8 @@ readonly def + //SAFETY /safe //true .forceput % overrides readonly + } .bind executeonly odef + ++currentdict /tempfilepaths undef ++ + /.setsafe + { + SAFETY /safe get not { +@@ -2095,30 +2107,6 @@ readonly def + .locksafe + } .bind executeonly odef + +-/deletefile { +- dup { deletefile } stopped { +- pop //deletefile $error /errorname get signalerror +- } { +- % deletefile succeeded. Remove from tempfile list if present +- //SAFETY /tempfiles get exch cvn 2 copy known { +- .forceundef +- } { +- pop pop +- } +- ifelse +- } +- ifelse +-} .bind executeonly odef +- +-% If a file is opened with .tempfile with SAFER not (yet) set, +-% the file can be deleted later, even if SAFER is set. +-/.tempfile { +- .tempfile % filename file +- //SAFETY /safe get not { % only add the filename if we're not yet safe +- //SAFETY /tempfiles get 2 .argindex //true .forceput +- } if +-} .bind executeonly odef +- + % If we are running in SAFER mode, lock things down + SAFER { .setsafe } if + diff --git a/SPECS/ghostscript.spec b/SPECS/ghostscript.spec index 47efee6..38f9e4e 100644 --- a/SPECS/ghostscript.spec +++ b/SPECS/ghostscript.spec @@ -5,7 +5,7 @@ Summary: A PostScript interpreter and renderer Name: ghostscript Version: %{gs_ver} -Release: 31%{?dist}.6 +Release: 31%{?dist}.9 # Included CMap data is Redistributable, no modification permitted, # see http://bugzilla.redhat.com/487510 @@ -52,6 +52,7 @@ Patch35: ghostscript-fix-pxl-devices-printing.patch Patch36: ghostscript-more-than-11-elements-in-array.patch Patch41: ghostscript-remove-as-many-non-standard-operators-as-possible.patch Patch47: ghostscript-restore-flushpage.patch +Patch57: ghostscript-pdf2ps-reports-error-when-reading-stdin.patch # Security patches: # ----------------- @@ -80,6 +81,11 @@ Patch53: ghostscript-cve-2018-18073.patch Patch54: ghostscript-cve-2018-17961.patch Patch55: ghostscript-cve-2018-18284.patch Patch56: ghostscript-cve-2018-19134.patch +Patch58: ghostscript-cve-2018-16540.patch +Patch59: ghostscript-cve-2018-19475.patch +Patch60: ghostscript-cve-2018-19476.patch +Patch61: ghostscript-cve-2018-19477.patch +Patch62: ghostscript-cve-2019-6116.patch # Upstream is not versioning the SONAME correctly, thus the rpmbuild is unable # to recognize we need a newer version of lcms2. This 'hackish' workaround @@ -337,6 +343,24 @@ rm -rf expat freetype icclib jasper jpeg lcms lcms2 libpng openjpeg zlib cups/li # CVE-2018-19134 (bug #1655937): %patch56 -p1 +# pdf2ps reports an error when reading from stdin (bug #1665919): +%patch57 -p1 + +# CVE-2018-16540 (bug #1657333): +%patch58 -p1 + +# CVE-2018-19475 (bug #1660569): +%patch59 -p1 + +# CVE-2018-19476 (bug #1660828): +%patch60 -p1 + +# CVE-2018-19477 (bug #1661278): +%patch61 -p1 + +# CVE-2019-6116 (bug 1667442): +%patch62 -p1 + # Remove pdfopt man pages which were mistakenly left in (bug #963882). rm man/{de/,}pdfopt.1 @@ -536,6 +560,24 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/libgs.so %changelog +* Thu Jan 24 2019 Martin Osvald <mosvald@redhat.com> - 9.07-31.el7_6.9 +- Related: #1667442 - CVE-2019-6116 - added missing parts of patch + +* Fri Jan 18 2019 Martin Osvald <mosvald@redhat.com> - 9.07-31.el7_6.8 +- Resolves: #1667442 - CVE-2019-6116 ghostscript: subroutines within + pseudo-operators must themselves be pseudo-operators + +* Thu Dec 20 2018 Martin Osvald <mosvald@redhat.com> - 9.07-31.el7_6.7 +- Resolves: #1665919 pdf2ps reports an error when reading from stdin +- Resolves: #1657333 - CVE-2018-16540 ghostscript: use-after-free in + copydevice handling (699661) +- Resolves: #1660569 - CVE-2018-19475 ghostscript: access bypass in + psi/zdevice2.c (700153) +- Resolves: #1660828 - CVE-2018-19476 ghostscript: access bypass in + psi/zicc.c +- Resolves: #1661278 - CVE-2018-19477 ghostscript: access bypass in + psi/zfjbig2.c (700168) + * Mon Dec 10 2018 Martin Osvald <mosvald@redhat.com> - 9.07-31.el7_6.6 - Resolves: #1657822 - ghostscript: Regression: Warning: Dropping incorrect smooth shading object (Error: /rangecheck in --run--)