From 30cd347f37bfb293ffdc407397d1023628400b81 Mon Sep 17 00:00:00 2001 From: Ken Sharp <ken.sharp@artifex.com> Date: Mon, 15 Oct 2018 13:35:15 +0100 Subject: [PATCH] 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. --- Resource/Init/gs_cff.ps | 4 ++-- Resource/Init/gs_cidcm.ps | 6 ++--- Resource/Init/gs_ciddc.ps | 4 ++-- Resource/Init/gs_cmap.ps | 2 +- Resource/Init/gs_res.ps | 60 +++++++++++++++++++++++------------------------ psi/zfont2.c | 4 ++++ 6 files changed, 42 insertions(+), 38 deletions(-) diff --git a/Resource/Init/gs_cff.ps b/Resource/Init/gs_cff.ps index 20c35a5..b60e374 100644 --- a/Resource/Init/gs_cff.ps +++ b/Resource/Init/gs_cff.ps @@ -199,7 +199,7 @@ def % 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. @@ -234,7 +234,7 @@ def end % FontSetInit ProcSet /FontSet defineresource -} bind def +} bind executeonly def % ---------------- Resource category definition ---------------- % diff --git a/Resource/Init/gs_cidcm.ps b/Resource/Init/gs_cidcm.ps index 0201ea8..60b0fdb 100644 --- a/Resource/Init/gs_cidcm.ps +++ b/Resource/Init/gs_cidcm.ps @@ -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 --git a/Resource/Init/gs_ciddc.ps b/Resource/Init/gs_ciddc.ps index 54c6876..f83e960 100644 --- a/Resource/Init/gs_ciddc.ps +++ b/Resource/Init/gs_ciddc.ps @@ -204,7 +204,7 @@ begin exch pop begin % .GetCIDDecoding end - } bind def + } bind executeonly def /FindResource % <name> FindResource <dict> { currentglobal exch % bGlobal /InstName @@ -212,7 +212,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 --git a/Resource/Init/gs_cmap.ps b/Resource/Init/gs_cmap.ps index 63c023b..a01afc2 100644 --- a/Resource/Init/gs_cmap.ps +++ b/Resource/Init/gs_cmap.ps @@ -536,7 +536,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 --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps index d1e10c9..9bdb8ff 100644 --- a/Resource/Init/gs_res.ps +++ b/Resource/Init/gs_res.ps @@ -155,10 +155,10 @@ setglobal } { /defineresource cvx /typecheck signaloperror } ifelse -} bind def +} bind executeonly def /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. @@ -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) @@ -586,7 +586,7 @@ status { ifelse } ifelse exch copy % (p/c/n) -} bind +} bind executeonly % Additional entries @@ -752,17 +752,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 @@ -865,7 +865,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 @@ -888,7 +888,7 @@ userdict /.localcsdefaults //false put } { pop } ifelse -} bind +} bind executeonly .definecategory % ColorSpace @@ -918,7 +918,7 @@ userdict /.localcsdefaults //false put { exch copy exch pop } { /Generic /Category findresource /ResourceFileName get exec } ifelse - } bind + } bind executeonly .definecategory % Encoding @@ -991,11 +991,11 @@ currentdict /.fontstatusaux .undef /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 @@ -1006,14 +1006,14 @@ currentdict /.fontstatusaux .undef .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 @@ -1063,20 +1063,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 --git a/psi/zfont2.c b/psi/zfont2.c index bed6c81..3123f19 100644 --- a/psi/zfont2.c +++ b/psi/zfont2.c @@ -2745,9 +2745,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); -- 2.9.1