Brad Bishop | d89cb5f | 2019-04-10 09:02:41 -0400 | [diff] [blame^] | 1 | From 20001d2bdf3cc60e76241a6ae72b1df01c5424c5 Mon Sep 17 00:00:00 2001 |
| 2 | From: Chris Liddell <chris.liddell@artifex.com> |
| 3 | Date: Thu, 13 Dec 2018 15:28:34 +0000 |
| 4 | Subject: [PATCH 2/7] Any transient procedures that call .force* operators |
| 5 | |
| 6 | (i.e. for conditionals or loops) make them executeonly. |
| 7 | |
| 8 | CVE: CVE-2019-6116 |
| 9 | Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git] |
| 10 | |
| 11 | Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com> |
| 12 | --- |
| 13 | Resource/Init/gs_diskn.ps | 2 +- |
| 14 | Resource/Init/gs_dps1.ps | 4 ++-- |
| 15 | Resource/Init/gs_fntem.ps | 4 ++-- |
| 16 | Resource/Init/gs_fonts.ps | 12 ++++++------ |
| 17 | Resource/Init/gs_init.ps | 4 ++-- |
| 18 | Resource/Init/gs_lev2.ps | 11 ++++++----- |
| 19 | Resource/Init/gs_pdfwr.ps | 2 +- |
| 20 | Resource/Init/gs_res.ps | 4 ++-- |
| 21 | Resource/Init/gs_setpd.ps | 2 +- |
| 22 | Resource/Init/pdf_base.ps | 13 ++++++++----- |
| 23 | Resource/Init/pdf_draw.ps | 16 +++++++++------- |
| 24 | Resource/Init/pdf_font.ps | 6 +++--- |
| 25 | Resource/Init/pdf_main.ps | 4 ++-- |
| 26 | Resource/Init/pdf_ops.ps | 7 ++++--- |
| 27 | 14 files changed, 49 insertions(+), 42 deletions(-) |
| 28 | |
| 29 | diff --git a/Resource/Init/gs_diskn.ps b/Resource/Init/gs_diskn.ps |
| 30 | index fd694bc..8bf2054 100644 |
| 31 | --- a/Resource/Init/gs_diskn.ps |
| 32 | +++ b/Resource/Init/gs_diskn.ps |
| 33 | @@ -51,7 +51,7 @@ systemdict begin |
| 34 | mark 5 1 roll ] mark exch { { } forall } forall ] |
| 35 | //systemdict /.searchabledevs 2 index .forceput |
| 36 | exch .setglobal |
| 37 | - } |
| 38 | + } executeonly |
| 39 | if |
| 40 | } .bind executeonly odef % must be bound and hidden for .forceput |
| 41 | |
| 42 | diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps |
| 43 | index ec5db61..4fae283 100644 |
| 44 | --- a/Resource/Init/gs_dps1.ps |
| 45 | +++ b/Resource/Init/gs_dps1.ps |
| 46 | @@ -78,7 +78,7 @@ level2dict begin |
| 47 | .currentglobal |
| 48 | { % Current mode is global; delete from local directory too. |
| 49 | //systemdict /LocalFontDirectory .knownget |
| 50 | - { 1 index .forceundef } % LocalFontDirectory is readonly |
| 51 | + { 1 index .forceundef } executeonly % LocalFontDirectory is readonly |
| 52 | if |
| 53 | } |
| 54 | { % Current mode is local; if there was a shadowed global |
| 55 | @@ -126,7 +126,7 @@ level2dict begin |
| 56 | } |
| 57 | ifelse |
| 58 | } forall |
| 59 | - pop counttomark 2 idiv { .forceundef } repeat pop % readonly |
| 60 | + pop counttomark 2 idiv { .forceundef } executeonly repeat pop % readonly |
| 61 | } |
| 62 | if |
| 63 | //SharedFontDirectory exch .forcecopynew pop |
| 64 | diff --git a/Resource/Init/gs_fntem.ps b/Resource/Init/gs_fntem.ps |
| 65 | index c1f7651..6eb672a 100644 |
| 66 | --- a/Resource/Init/gs_fntem.ps |
| 67 | +++ b/Resource/Init/gs_fntem.ps |
| 68 | @@ -401,12 +401,12 @@ currentdict end def |
| 69 | .forceput % FontInfo can be read-only. |
| 70 | pop % bool <font> |
| 71 | exit |
| 72 | - } if |
| 73 | + } executeonly if |
| 74 | dup /FontInfo get % bool <font> <FI> |
| 75 | /GlyphNames2Unicode /Unicode /Decoding findresource |
| 76 | .forceput % FontInfo can be read-only. |
| 77 | exit |
| 78 | - } loop |
| 79 | + } executeonly loop |
| 80 | exch setglobal |
| 81 | } .bind executeonly odef % must be bound and hidden for .forceput |
| 82 | |
| 83 | diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps |
| 84 | index 803faca..290da0c 100644 |
| 85 | --- a/Resource/Init/gs_fonts.ps |
| 86 | +++ b/Resource/Init/gs_fonts.ps |
| 87 | @@ -374,7 +374,7 @@ FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if |
| 88 | /.setnativefontmapbuilt { % set whether we've been run |
| 89 | dup type /booleantype eq { |
| 90 | systemdict exch /.nativefontmapbuilt exch .forceput |
| 91 | - } |
| 92 | + } executeonly |
| 93 | {pop} |
| 94 | ifelse |
| 95 | } .bind executeonly odef |
| 96 | @@ -1007,11 +1007,11 @@ $error /SubstituteFont { } put |
| 97 | { 2 index gcheck currentglobal |
| 98 | 2 copy eq { |
| 99 | pop pop .forceput |
| 100 | - } { |
| 101 | + } executeonly { |
| 102 | 5 1 roll setglobal |
| 103 | dup length string copy |
| 104 | .forceput setglobal |
| 105 | - } ifelse |
| 106 | + } executeonly ifelse |
| 107 | } .bind executeonly odef % must be bound and hidden for .forceput |
| 108 | |
| 109 | % Attempt to load a font from a file. |
| 110 | @@ -1084,7 +1084,7 @@ $error /SubstituteFont { } put |
| 111 | .FontDirectory 3 index .forceundef % readonly |
| 112 | 1 index (r) file .loadfont .FontDirectory exch |
| 113 | /.setglobal .systemvar exec |
| 114 | - } |
| 115 | + } executeonly |
| 116 | { .loadfont .FontDirectory |
| 117 | } |
| 118 | ifelse |
| 119 | @@ -1105,7 +1105,7 @@ $error /SubstituteFont { } put |
| 120 | dup 3 index .fontknownget |
| 121 | { dup /PathLoad 4 index .putgstringcopy |
| 122 | 4 1 roll pop pop pop //true exit |
| 123 | - } if |
| 124 | + } executeonly if |
| 125 | |
| 126 | % Maybe the file had a different FontName. |
| 127 | % See if we can get a FontName from the file, and if so, |
| 128 | @@ -1134,7 +1134,7 @@ $error /SubstituteFont { } put |
| 129 | ifelse % Stack: origfontname fontdict |
| 130 | exch pop //true exit |
| 131 | % Stack: fontdict |
| 132 | - } |
| 133 | + } executeonly |
| 134 | if pop % Stack: origfontname fontdirectory path |
| 135 | } |
| 136 | if pop pop % Stack: origfontname |
| 137 | diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps |
| 138 | index d733124..56c0bd2 100644 |
| 139 | --- a/Resource/Init/gs_init.ps |
| 140 | +++ b/Resource/Init/gs_init.ps |
| 141 | @@ -2357,7 +2357,7 @@ SAFER { .setsafeglobal } if |
| 142 | % Update the copy of the user parameters. |
| 143 | mark .currentuserparams counttomark 2 idiv { |
| 144 | userparams 3 1 roll .forceput % userparams is read-only |
| 145 | - } repeat pop |
| 146 | + } executeonly repeat pop |
| 147 | % Turn on idiom recognition, if available. |
| 148 | currentuserparams /IdiomRecognition known { |
| 149 | /IdiomRecognition //true .definepsuserparam |
| 150 | @@ -2376,7 +2376,7 @@ SAFER { .setsafeglobal } if |
| 151 | % Remove real system params from pssystemparams. |
| 152 | mark .currentsystemparams counttomark 2 idiv { |
| 153 | pop pssystemparams exch .forceundef |
| 154 | - } repeat pop |
| 155 | + } executeonly repeat pop |
| 156 | } if |
| 157 | |
| 158 | % Set up AlignToPixels : |
| 159 | diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps |
| 160 | index 44fe619..0f0d573 100644 |
| 161 | --- a/Resource/Init/gs_lev2.ps |
| 162 | +++ b/Resource/Init/gs_lev2.ps |
| 163 | @@ -154,7 +154,8 @@ end |
| 164 | % protect top level of parameters that we copied |
| 165 | dup type dup /arraytype eq exch /stringtype eq or { readonly } if |
| 166 | /userparams .systemvar 3 1 roll .forceput % userparams is read-only |
| 167 | - } { |
| 168 | + } executeonly |
| 169 | + { |
| 170 | pop pop |
| 171 | } ifelse |
| 172 | } forall |
| 173 | @@ -224,7 +225,7 @@ end |
| 174 | % protect top level parameters that we copied |
| 175 | dup type dup /arraytype eq exch /stringtype eq or { readonly } if |
| 176 | //pssystemparams 3 1 roll .forceput % pssystemparams is read-only |
| 177 | - } |
| 178 | + } executeonly |
| 179 | { pop pop |
| 180 | } |
| 181 | ifelse |
| 182 | @@ -934,7 +935,7 @@ mark |
| 183 | dup /PaintProc get |
| 184 | 1 index /Implementation known not { |
| 185 | 1 index dup /Implementation //null .forceput readonly pop |
| 186 | - } if |
| 187 | + } executeonly if |
| 188 | exec |
| 189 | }.bind odef |
| 190 | |
| 191 | @@ -958,7 +959,7 @@ mark |
| 192 | dup /PaintProc get |
| 193 | 1 index /Implementation known not { |
| 194 | 1 index dup /Implementation //null .forceput readonly pop |
| 195 | - } if |
| 196 | + } executeonly if |
| 197 | /UNROLLFORMS where {/UNROLLFORMS get}{false}ifelse not |
| 198 | %% [CTM] <<Form>> PaintProc .beginform - |
| 199 | { |
| 200 | @@ -1005,7 +1006,7 @@ mark |
| 201 | %% Form dictioanry using the /Implementation key). |
| 202 | 1 dict dup /FormID 4 -1 roll put |
| 203 | 1 index exch /Implementation exch .forceput readonly pop |
| 204 | - } |
| 205 | + } executeonly |
| 206 | ifelse |
| 207 | } |
| 208 | { |
| 209 | diff --git a/Resource/Init/gs_pdfwr.ps b/Resource/Init/gs_pdfwr.ps |
| 210 | index 58e75d3..b425103 100644 |
| 211 | --- a/Resource/Init/gs_pdfwr.ps |
| 212 | +++ b/Resource/Init/gs_pdfwr.ps |
| 213 | @@ -650,7 +650,7 @@ currentdict /.pdfmarkparams .undef |
| 214 | } ifelse |
| 215 | } bind .makeoperator .forceput |
| 216 | systemdict /.pdf_hooked_DSC_Creator //true .forceput |
| 217 | - } if |
| 218 | + } executeonly if |
| 219 | pop |
| 220 | } if |
| 221 | } { |
| 222 | diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps |
| 223 | index 8eb8bb0..d9b3459 100644 |
| 224 | --- a/Resource/Init/gs_res.ps |
| 225 | +++ b/Resource/Init/gs_res.ps |
| 226 | @@ -152,7 +152,7 @@ setglobal |
| 227 | % use .forceput / .forcedef later to replace the dummy, |
| 228 | % empty .Instances dictionary with the real one later. |
| 229 | readonly |
| 230 | - } { |
| 231 | + }{ |
| 232 | /defineresource cvx /typecheck signaloperror |
| 233 | } ifelse |
| 234 | } bind executeonly odef |
| 235 | @@ -424,7 +424,7 @@ status { |
| 236 | % As noted above, Category dictionaries are read-only, |
| 237 | % so we have to use .forcedef here. |
| 238 | /.Instances 1 index .forcedef % Category dict is read-only |
| 239 | - } if |
| 240 | + } executeonly if |
| 241 | } |
| 242 | { .LocalInstances dup //.emptydict eq |
| 243 | { pop 3 dict localinstancedict Category 2 index put |
| 244 | diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps |
| 245 | index e22597e..7875d1f 100644 |
| 246 | --- a/Resource/Init/gs_setpd.ps |
| 247 | +++ b/Resource/Init/gs_setpd.ps |
| 248 | @@ -634,7 +634,7 @@ NOMEDIAATTRS { |
| 249 | SETPDDEBUG { (Rolling back.) = pstack flush } if |
| 250 | 3 index 2 index 3 -1 roll .forceput |
| 251 | 4 index 1 index .knownget |
| 252 | - { 4 index 3 1 roll .forceput } |
| 253 | + { 4 index 3 1 roll .forceput } executeonly |
| 254 | { 3 index exch .undef } |
| 255 | ifelse |
| 256 | } bind executeonly odef |
| 257 | diff --git a/Resource/Init/pdf_base.ps b/Resource/Init/pdf_base.ps |
| 258 | index b45e980..7312729 100644 |
| 259 | --- a/Resource/Init/pdf_base.ps |
| 260 | +++ b/Resource/Init/pdf_base.ps |
| 261 | @@ -130,26 +130,29 @@ currentdict /num-chars-dict .undef |
| 262 | |
| 263 | /.pdfexectoken { % <count> <opdict> <exectoken> .pdfexectoken ? |
| 264 | PDFDEBUG { |
| 265 | - pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } if |
| 266 | + pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } executeonly if |
| 267 | PDFSTEP { |
| 268 | pdfdict /PDFtokencount 2 copy .knownget { 1 add } { 1 } ifelse .forceput |
| 269 | PDFSTEPcount 1 gt { |
| 270 | pdfdict /PDFSTEPcount PDFSTEPcount 1 sub .forceput |
| 271 | - } { |
| 272 | + } executeonly |
| 273 | + { |
| 274 | dup ==only |
| 275 | ( step # ) print PDFtokencount =only |
| 276 | ( ? ) print flush 1 //false .outputpage |
| 277 | (%stdin) (r) file 255 string readline { |
| 278 | token { |
| 279 | exch pop pdfdict /PDFSTEPcount 3 -1 roll .forceput |
| 280 | - } { |
| 281 | + } executeonly |
| 282 | + { |
| 283 | pdfdict /PDFSTEPcount 1 .forceput |
| 284 | - } ifelse % token |
| 285 | + } executeonly ifelse % token |
| 286 | } { |
| 287 | pop /PDFSTEP //false def % EOF on stdin |
| 288 | } ifelse % readline |
| 289 | } ifelse % PDFSTEPcount > 1 |
| 290 | - } { |
| 291 | + } executeonly |
| 292 | + { |
| 293 | dup ==only () = flush |
| 294 | } ifelse % PDFSTEP |
| 295 | } if % PDFDEBUG |
| 296 | diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps |
| 297 | index 6b0ba93..40c6ac8 100644 |
| 298 | --- a/Resource/Init/pdf_draw.ps |
| 299 | +++ b/Resource/Init/pdf_draw.ps |
| 300 | @@ -1118,14 +1118,14 @@ currentdict end readonly def |
| 301 | pdfdict /.Qqwarning_issued //true .forceput |
| 302 | .setglobal |
| 303 | pdfformaterror |
| 304 | - } ifelse |
| 305 | + } executeonly ifelse |
| 306 | } |
| 307 | { |
| 308 | currentglobal pdfdict gcheck .setglobal |
| 309 | pdfdict /.Qqwarning_issued //true .forceput |
| 310 | .setglobal |
| 311 | pdfformaterror |
| 312 | - } ifelse |
| 313 | + } executeonly ifelse |
| 314 | end |
| 315 | } ifelse |
| 316 | } loop |
| 317 | @@ -1141,14 +1141,14 @@ currentdict end readonly def |
| 318 | pdfdict /.Qqwarning_issued //true .forceput |
| 319 | .setglobal |
| 320 | pdfformaterror |
| 321 | - } ifelse |
| 322 | + } executeonly ifelse |
| 323 | } |
| 324 | { |
| 325 | currentglobal pdfdict gcheck .setglobal |
| 326 | pdfdict /.Qqwarning_issued //true .forceput |
| 327 | .setglobal |
| 328 | pdfformaterror |
| 329 | - } ifelse |
| 330 | + } executeonly ifelse |
| 331 | } if |
| 332 | pop |
| 333 | |
| 334 | @@ -2350,9 +2350,10 @@ currentdict /last-ditch-bpc-csp undef |
| 335 | /IncrementAppearanceNumber { |
| 336 | pdfdict /AppearanceNumber .knownget { |
| 337 | 1 add pdfdict /AppearanceNumber 3 -1 roll .forceput |
| 338 | - }{ |
| 339 | + } executeonly |
| 340 | + { |
| 341 | pdfdict /AppearanceNumber 0 .forceput |
| 342 | - } ifelse |
| 343 | + } executeonly ifelse |
| 344 | }bind executeonly odef |
| 345 | |
| 346 | /MakeAppearanceName { |
| 347 | @@ -2510,7 +2511,8 @@ currentdict /last-ditch-bpc-csp undef |
| 348 | %% want to preserve it. |
| 349 | pdfdict /.PreservePDFForm false .forceput |
| 350 | /q cvx /execform cvx 5 -2 roll |
| 351 | - }{ |
| 352 | + } executeonly |
| 353 | + { |
| 354 | /q cvx /PDFexecform cvx 5 -2 roll |
| 355 | } ifelse |
| 356 | |
| 357 | diff --git a/Resource/Init/pdf_font.ps b/Resource/Init/pdf_font.ps |
| 358 | index bea9ea9..4cd62b9 100644 |
| 359 | --- a/Resource/Init/pdf_font.ps |
| 360 | +++ b/Resource/Init/pdf_font.ps |
| 361 | @@ -714,7 +714,7 @@ currentdict end readonly def |
| 362 | pop pop pop |
| 363 | currentdict /.stackdepth .forceundef |
| 364 | currentdict /.dstackdepth .forceundef |
| 365 | - } |
| 366 | + } executeonly |
| 367 | {pop pop pop} |
| 368 | ifelse |
| 369 | |
| 370 | @@ -1232,7 +1232,7 @@ currentdict /eexec_pdf_param_dict .undef |
| 371 | (\n **** Warning: Type 3 glyph has unbalanced q/Q operators \(too many q's\)\n Output may be incorrect.\n) |
| 372 | pdfformatwarning |
| 373 | pdfdict /.Qqwarning_issued //true .forceput |
| 374 | - } if |
| 375 | + } executeonly if |
| 376 | Q |
| 377 | } repeat |
| 378 | Q |
| 379 | @@ -2016,7 +2016,7 @@ currentdict /CMap_read_dict undef |
| 380 | /CIDFallBack /CIDFont findresource |
| 381 | } if |
| 382 | exit |
| 383 | - } if |
| 384 | + } executeonly if |
| 385 | } if |
| 386 | } if |
| 387 | |
| 388 | diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps |
| 389 | index 00da47a..37e69b3 100644 |
| 390 | --- a/Resource/Init/pdf_main.ps |
| 391 | +++ b/Resource/Init/pdf_main.ps |
| 392 | @@ -2701,14 +2701,14 @@ currentdict /PDF2PS_matrix_key undef |
| 393 | pdfdict /.Qqwarning_issued //true .forceput |
| 394 | .setglobal |
| 395 | pdfformaterror |
| 396 | - } ifelse |
| 397 | + } executeonly ifelse |
| 398 | } |
| 399 | { |
| 400 | currentglobal pdfdict gcheck .setglobal |
| 401 | pdfdict /.Qqwarning_issued //true .forceput |
| 402 | .setglobal |
| 403 | pdfformaterror |
| 404 | - } ifelse |
| 405 | + } executeonly ifelse |
| 406 | } if |
| 407 | } if |
| 408 | pop |
| 409 | diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps |
| 410 | index 8672d61..aa09641 100644 |
| 411 | --- a/Resource/Init/pdf_ops.ps |
| 412 | +++ b/Resource/Init/pdf_ops.ps |
| 413 | @@ -184,14 +184,14 @@ currentdict /gput_always_allow .undef |
| 414 | pdfdict /.Qqwarning_issued //true .forceput |
| 415 | .setglobal |
| 416 | pdfformaterror |
| 417 | - } ifelse |
| 418 | + } executeonly ifelse |
| 419 | } |
| 420 | { |
| 421 | currentglobal pdfdict gcheck .setglobal |
| 422 | pdfdict /.Qqwarning_issued //true .forceput |
| 423 | .setglobal |
| 424 | pdfformaterror |
| 425 | - } ifelse |
| 426 | + } executeonly ifelse |
| 427 | } if |
| 428 | } bind executeonly odef |
| 429 | |
| 430 | @@ -439,7 +439,8 @@ currentdict /gput_always_allow .undef |
| 431 | dup type /booleantype eq { |
| 432 | .currentSMask type /dicttype eq { |
| 433 | .currentSMask /Processed 2 index .forceput |
| 434 | - } { |
| 435 | + } executeonly |
| 436 | + { |
| 437 | .setSMask |
| 438 | }ifelse |
| 439 | }{ |
| 440 | -- |
| 441 | 2.18.1 |
| 442 | |