Original Submitted By: Ken Moffat Updated By: Douglas R. Reno Date: 2019-08-14 Updated Date: 2019-10-09 Initial Package Version: 9.27 Upstream Status: Applied Origin: Ghostscript Git Repository (previous patch came from Debian Security) Description: Fixes CVE-2019-10216 Updated Description: Fixes new vulnerabilities CVE-2019-14811, CVE-2019-14812, CVE-2019-14813, and CVE-2019-14817 (Safer Mode Bypass). diff -Naurp ghostscript-9.27.orig/base/fapi_ft.c ghostscript-9.27/base/fapi_ft.c --- ghostscript-9.27.orig/base/fapi_ft.c 2019-04-04 02:43:14.000000000 -0500 +++ ghostscript-9.27/base/fapi_ft.c 2019-10-09 22:25:27.222924814 -0500 @@ -974,13 +974,19 @@ make_rotation(FT_Matrix * a_transform, c */ static void transform_decompose(FT_Matrix * a_transform, FT_UInt * xresp, FT_UInt * yresp, - FT_Fixed * a_x_scale, FT_Fixed * a_y_scale) + FT_Fixed * a_x_scale, FT_Fixed * a_y_scale, int units_per_EM) { double scalex, scaley, fact = 1.0; double factx = 1.0, facty = 1.0; FT_Matrix ftscale_mat; FT_UInt xres; FT_UInt yres; + /* We have to account for units_per_EM as we fiddle with the scaling + * in order to avoid underflow (mostly in the TTF hinting code), but + * we also want to clamp to a lower value (512, admittedly arrived at + * via experimentation) in order to preserve the fidelity of the outlines. + */ + double upe = units_per_EM > 512 ? (float)units_per_EM : 512.0; scalex = hypot((double)a_transform->xx, (double)a_transform->xy); scaley = hypot((double)a_transform->yx, (double)a_transform->yy); @@ -1067,10 +1073,25 @@ transform_decompose(FT_Matrix * a_transf scalex *= fact; } - ftscale_mat.xx = (FT_Fixed) (65536.0 / scalex); - ftscale_mat.xy = (FT_Fixed) 0; - ftscale_mat.yx = (FT_Fixed) 0; - ftscale_mat.yy = (FT_Fixed) (65536.0 / scaley); + /* see above */ + fact = 1.0; + while (scaley * yres > (double)upe * 72.0 && (xres > 0 && yres > 0) + && (scalex > 0.0 && scaley > 0.0)) { + if (scaley < yres) { + xres >>= 1; + yres >>= 1; + fact *= 2.0; + } + else { + scalex /= 1.25; + scaley /= 1.25; + } + } + + ftscale_mat.xx = (FT_Fixed) ((65536.0 / scalex) * fact); + ftscale_mat.xy = 0; + ftscale_mat.yx = 0; + ftscale_mat.yy = (FT_Fixed) ((65536.0 / scaley) * fact); FT_Matrix_Multiply(a_transform, &ftscale_mat); memcpy(a_transform, &ftscale_mat, sizeof(FT_Matrix)); @@ -1315,7 +1336,7 @@ gs_fapi_ft_get_scaled_font(gs_fapi_serve * transform. */ transform_decompose(&face->ft_transform, &face->horz_res, - &face->vert_res, &face->width, &face->height); + &face->vert_res, &face->width, &face->height, face->ft_face->units_per_EM); ft_error = FT_Set_Char_Size(face->ft_face, face->width, face->height, face->horz_res, face->vert_res); diff -Naurp ghostscript-9.27.orig/Resource/Init/gs_lev2.ps ghostscript-9.27/Resource/Init/gs_lev2.ps --- ghostscript-9.27.orig/Resource/Init/gs_lev2.ps 2019-04-04 02:43:14.000000000 -0500 +++ ghostscript-9.27/Resource/Init/gs_lev2.ps 2019-10-09 22:26:20.430212715 -0500 @@ -158,7 +158,7 @@ end { pop pop } ifelse - } forall + } executeonly forall % A context switch might have occurred during the above loop, % causing the interpreter-level parameters to be reset. % Set them again to the new values. From here on, we are safe, @@ -229,9 +229,9 @@ end { pop pop } ifelse - } + } executeonly forall pop -} .bind odef +} .bind executeonly odef % Initialize the passwords. % NOTE: the names StartJobPassword and SystemParamsPassword are known to diff -Naurp ghostscript-9.27.orig/Resource/Init/gs_pdfwr.ps ghostscript-9.27/Resource/Init/gs_pdfwr.ps --- ghostscript-9.27.orig/Resource/Init/gs_pdfwr.ps 2019-04-04 02:43:14.000000000 -0500 +++ ghostscript-9.27/Resource/Init/gs_pdfwr.ps 2019-10-09 22:27:00.227417463 -0500 @@ -652,11 +652,11 @@ currentdict /.pdfmarkparams .undef systemdict /.pdf_hooked_DSC_Creator //true .forceput } executeonly if pop - } if + } executeonly if } { pop } ifelse - } + } executeonly { pop } ifelse diff -Naurp ghostscript-9.27.orig/Resource/Init/gs_type1.ps ghostscript-9.27/Resource/Init/gs_type1.ps --- ghostscript-9.27.orig/Resource/Init/gs_type1.ps 2019-04-04 02:43:14.000000000 -0500 +++ ghostscript-9.27/Resource/Init/gs_type1.ps 2019-10-09 22:25:27.223924819 -0500 @@ -118,25 +118,25 @@ ( to be the same as glyph: ) print 1 index //== exec } if 3 index exch 3 index .forceput % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname - } + }executeonly {pop} ifelse - } forall + } executeonly forall pop pop - } + } executeonly { pop pop pop } ifelse - } + } executeonly { % scratch(string) RAGL(dict) AGL(dict) CharStrings(dict) cstring gname pop pop } ifelse - } forall + } executeonly forall 3 1 roll pop pop - } if + } executeonly if pop dup /.AGLprocessed~GS //true .forceput - } if + } executeonly if %% We need to excute the C .buildfont1 in a stopped context so that, if there %% are errors we can put the stack back sanely and exit. Otherwise callers won't diff -Naurp ghostscript-9.27.orig/Resource/Init/pdf_base.ps ghostscript-9.27/Resource/Init/pdf_base.ps --- ghostscript-9.27.orig/Resource/Init/pdf_base.ps 2019-04-04 02:43:14.000000000 -0500 +++ ghostscript-9.27/Resource/Init/pdf_base.ps 2019-10-09 22:28:34.075868531 -0500 @@ -157,7 +157,7 @@ currentdict /num-chars-dict .undef { dup ==only () = flush } ifelse % PDFSTEP - } if % PDFDEBUG + } executeonly if % PDFDEBUG 2 copy .knownget { exch pop exch pop exch pop exec } { diff -Naurp ghostscript-9.27.orig/Resource/Init/pdf_draw.ps ghostscript-9.27/Resource/Init/pdf_draw.ps --- ghostscript-9.27.orig/Resource/Init/pdf_draw.ps 2019-04-04 02:43:14.000000000 -0500 +++ ghostscript-9.27/Resource/Init/pdf_draw.ps 2019-10-09 22:30:18.052323566 -0500 @@ -501,8 +501,8 @@ end ( Output may be incorrect.\n) pdfformaterror //pdfdict /.gs_warning_issued //true .forceput PDFSTOPONERROR { /gs /undefined signalerror } if - } if - } + } executeonly if + } executeonly ifelse } bind executeonly def @@ -1142,7 +1142,7 @@ currentdict end readonly def .setglobal pdfformaterror } executeonly ifelse - } + } executeonly { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput @@ -1150,8 +1150,8 @@ currentdict end readonly def pdfformaterror } executeonly ifelse end - } ifelse - } loop + } executeonly ifelse + } executeonly loop { (\n **** Error: File has unbalanced q/Q operators \(too many q's\)\n Output may be incorrect.\n) //pdfdict /.Qqwarning_issued .knownget @@ -1165,14 +1165,14 @@ currentdict end readonly def .setglobal pdfformaterror } executeonly ifelse - } + } executeonly { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse - } if + } executeonly if pop % restore pdfemptycount diff -Naurp ghostscript-9.27.orig/Resource/Init/pdf_font.ps ghostscript-9.27/Resource/Init/pdf_font.ps --- ghostscript-9.27.orig/Resource/Init/pdf_font.ps 2019-04-04 02:43:14.000000000 -0500 +++ ghostscript-9.27/Resource/Init/pdf_font.ps 2019-10-09 22:35:22.421458715 -0500 @@ -677,7 +677,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 } { @@ -701,9 +701,9 @@ currentdict end readonly def } if PDFDEBUG { (.processToUnicode end) = - } if - } if - } stopped + } executeonly if + } executeonly if + } executeonly stopped { .dstackdepth 1 countdictstack 1 sub {pop end} for @@ -2045,9 +2045,9 @@ currentdict /CMap_read_dict undef (Will continue, but content may be missing.) = flush } ifelse } if - } if + } executeonly if /findresource cvx /undefined signalerror - } loop + } executeonly loop } bind executeonly odef /buildCIDType0 { % buildCIDType0 diff -Naurp ghostscript-9.27.orig/Resource/Init/pdf_main.ps ghostscript-9.27/Resource/Init/pdf_main.ps --- ghostscript-9.27.orig/Resource/Init/pdf_main.ps 2019-04-04 02:43:14.000000000 -0500 +++ ghostscript-9.27/Resource/Init/pdf_main.ps 2019-10-09 22:36:43.409724841 -0500 @@ -2749,15 +2749,15 @@ currentdict /PDF2PS_matrix_key undef .setglobal pdfformaterror } executeonly ifelse - } + } executeonly { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse - } if - } if + } executeonly if + } executeonly if pop count PDFexecstackcount sub { pop } repeat (after exec) VMDEBUG diff -Naurp ghostscript-9.27.orig/Resource/Init/pdf_ops.ps ghostscript-9.27/Resource/Init/pdf_ops.ps --- ghostscript-9.27.orig/Resource/Init/pdf_ops.ps 2019-04-04 02:43:14.000000000 -0500 +++ ghostscript-9.27/Resource/Init/pdf_ops.ps 2019-10-09 22:37:40.792906635 -0500 @@ -186,14 +186,14 @@ currentdict /gput_always_allow .undef .setglobal pdfformaterror } executeonly ifelse - } + } executeonly { currentglobal //pdfdict gcheck .setglobal //pdfdict /.Qqwarning_issued //true .forceput .setglobal pdfformaterror } executeonly ifelse - } if + } executeonly if } bind executeonly odef % Save PDF gstate