| From 430f39144244ba4fd7b720cf87031e415e0fabce Mon Sep 17 00:00:00 2001 |
| From: Chris Liddell <chris.liddell@artifex.com> |
| Date: Mon, 5 Nov 2018 15:42:52 +0800 |
| Subject: [PATCH 2/2] Bug 699927: don't include operator arrays in execstack |
| output |
| |
| When we transfer the contents of the execution stack into the array, take the |
| extra step of replacing any operator arrays on the stack with the operator |
| that reference them. |
| |
| This prevents the contents of Postscript defined, internal only operators (those |
| created with .makeoperator) being exposed via execstack (and thus, via error |
| handling). |
| |
| This necessitates a change in the resource remapping 'resource', which contains |
| a procedure which relies on the contents of the operators arrays being present. |
| As we already had internal-only variants of countexecstack and execstack |
| (.countexecstack and .execstack) - using those, and leaving thier operation |
| including the operator arrays means the procedure continues to work correctly. |
| |
| Both .countexecstack and .execstack are undefined after initialization. |
| |
| Also, when we store the execstack (or part thereof) for an execstackoverflow |
| error, make the same oparray/operator substitution as above for execstack. |
| |
| CVE: CVE-2018-18073 |
| Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git] |
| Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> |
| --- |
| Resource/Init/gs_init.ps | 4 ++-- |
| Resource/Init/gs_resmp.ps | 2 +- |
| psi/int.mak | 2 +- |
| psi/interp.c | 14 +++++++++++--- |
| psi/interp.h | 2 ++ |
| psi/zcontrol.c | 13 ++++++++++--- |
| 6 files changed, 27 insertions(+), 10 deletions(-) |
| |
| diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps |
| index 7c71d18..f4c1053 100644 |
| --- a/Resource/Init/gs_init.ps |
| +++ b/Resource/Init/gs_init.ps |
| @@ -2191,7 +2191,7 @@ SAFER { .setsafeglobal } if |
| %% but can be easily restored (just delete the name from the list in the array). In future |
| %% we may remove the operator and the code implementation entirely. |
| [ |
| - /.bitadd /.charboxpath /.cond /.countexecstack /.execstack /.runandhide /.popdevicefilter |
| + /.bitadd /.charboxpath /.cond /.runandhide /.popdevicefilter |
| /.execfile /.filenamesplit /.file_name_parent |
| /.setdefaultmatrix /.isprocfilter /.unread /.psstringencode |
| /.buildsampledfunction /.isencapfunction /.currentaccuratecurves /.currentcurvejoin /.currentdashadapt /.currentdotlength |
| @@ -2230,7 +2230,7 @@ SAFER { .setsafeglobal } if |
| /.localvmarray /.localvmdict /.localvmpackedarray /.localvmstring /.systemvmarray /.systemvmdict /.systemvmpackedarray /.systemvmstring /.systemvmfile /.systemvmlibfile |
| /.systemvmSFD /.settrapparams /.currentsystemparams /.currentuserparams /.getsystemparam /.getuserparam /.setsystemparams /.setuserparams |
| /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath |
| - /.type /.writecvs /.setSMask /.currentSMask |
| + /.type /.writecvs /.setSMask /.currentSMask /.countexecstack /.execstack |
| |
| % Used by a free user in the Library of Congress. Apparently this is used to |
| % draw a partial page, which is then filled in by the results of a barcode |
| diff --git a/Resource/Init/gs_resmp.ps b/Resource/Init/gs_resmp.ps |
| index 7cacaf8..9bb4263 100644 |
| --- a/Resource/Init/gs_resmp.ps |
| +++ b/Resource/Init/gs_resmp.ps |
| @@ -183,7 +183,7 @@ setpacking |
| % We don't check them. |
| |
| currentglobal //false setglobal % <object> bGlobal |
| - countexecstack array execstack % <object> bGlobal [execstack] |
| + //false .countexecstack array //false .execstack % <object> bGlobal [execstack] |
| dup //null exch % <object> bGlobal [execstack] null [execstack] |
| length 3 sub -1 0 { % <object> bGlobal [execstack] null i |
| 2 index exch get % <object> bGlobal [execstack] null proc |
| diff --git a/psi/int.mak b/psi/int.mak |
| index 5d9b3d5..6ab5bf0 100644 |
| --- a/psi/int.mak |
| +++ b/psi/int.mak |
| @@ -323,7 +323,7 @@ $(PSOBJ)zarray.$(OBJ) : $(PSSRC)zarray.c $(OP) $(memory__h)\ |
| |
| $(PSOBJ)zcontrol.$(OBJ) : $(PSSRC)zcontrol.c $(OP) $(string__h)\ |
| $(estack_h) $(files_h) $(ipacked_h) $(iutil_h) $(store_h) $(stream_h)\ |
| - $(INT_MAK) $(MAKEDIRS) |
| + $(interp_h) $(INT_MAK) $(MAKEDIRS) |
| $(PSCC) $(PSO_)zcontrol.$(OBJ) $(C_) $(PSSRC)zcontrol.c |
| |
| $(PSOBJ)zdict.$(OBJ) : $(PSSRC)zdict.c $(OP)\ |
| diff --git a/psi/interp.c b/psi/interp.c |
| index b70769d..6dc0dda 100644 |
| --- a/psi/interp.c |
| +++ b/psi/interp.c |
| @@ -142,7 +142,6 @@ static int oparray_pop(i_ctx_t *); |
| static int oparray_cleanup(i_ctx_t *); |
| static int zerrorexec(i_ctx_t *); |
| static int zfinderrorobject(i_ctx_t *); |
| -static int errorexec_find(i_ctx_t *, ref *); |
| static int errorexec_pop(i_ctx_t *); |
| static int errorexec_cleanup(i_ctx_t *); |
| static int zsetstackprotect(i_ctx_t *); |
| @@ -761,7 +760,7 @@ copy_stack(i_ctx_t *i_ctx_p, const ref_stack_t * pstack, int skip, ref * arr) |
| { |
| uint size = ref_stack_count(pstack) - skip; |
| uint save_space = ialloc_space(idmemory); |
| - int code; |
| + int code, i; |
| |
| if (size > 65535) |
| size = 65535; |
| @@ -770,6 +769,15 @@ copy_stack(i_ctx_t *i_ctx_p, const ref_stack_t * pstack, int skip, ref * arr) |
| if (code >= 0) |
| code = ref_stack_store(pstack, arr, size, 0, 1, true, idmemory, |
| "copy_stack"); |
| + /* If we are copying the exec stack, try to replace any oparrays with |
| + * with the operator than references them |
| + */ |
| + if (pstack == &e_stack) { |
| + for (i = 0; i < size; i++) { |
| + if (errorexec_find(i_ctx_p, &arr->value.refs[i]) < 0) |
| + make_null(&arr->value.refs[i]); |
| + } |
| + } |
| ialloc_set_space(idmemory, save_space); |
| return code; |
| } |
| @@ -1934,7 +1942,7 @@ zfinderrorobject(i_ctx_t *i_ctx_p) |
| * .errorexec with errobj != null, store it in *perror_object and return 1, |
| * otherwise return 0; |
| */ |
| -static int |
| +int |
| errorexec_find(i_ctx_t *i_ctx_p, ref *perror_object) |
| { |
| long i; |
| diff --git a/psi/interp.h b/psi/interp.h |
| index e9275b9..4f551d1 100644 |
| --- a/psi/interp.h |
| +++ b/psi/interp.h |
| @@ -91,5 +91,7 @@ void gs_interp_reset(i_ctx_t *i_ctx_p); |
| /* Define the top-level interface to the interpreter. */ |
| int gs_interpret(i_ctx_t **pi_ctx_p, ref * pref, int user_errors, |
| int *pexit_code, ref * perror_object); |
| +int |
| +errorexec_find(i_ctx_t *i_ctx_p, ref *perror_object); |
| |
| #endif /* interp_INCLUDED */ |
| diff --git a/psi/zcontrol.c b/psi/zcontrol.c |
| index 36da22c..0362cf4 100644 |
| --- a/psi/zcontrol.c |
| +++ b/psi/zcontrol.c |
| @@ -24,6 +24,7 @@ |
| #include "ipacked.h" |
| #include "iutil.h" |
| #include "store.h" |
| +#include "interp.h" |
| |
| /* Forward references */ |
| static int check_for_exec(const_os_ptr); |
| @@ -787,7 +788,7 @@ zexecstack2(i_ctx_t *i_ctx_p) |
| /* Continuation operator to do the actual transfer. */ |
| /* r_size(op1) was set just above. */ |
| static int |
| -do_execstack(i_ctx_t *i_ctx_p, bool include_marks, os_ptr op1) |
| +do_execstack(i_ctx_t *i_ctx_p, bool include_marks, bool include_oparrays, os_ptr op1) |
| { |
| os_ptr op = osp; |
| ref *arefs = op1->value.refs; |
| @@ -829,6 +830,12 @@ do_execstack(i_ctx_t *i_ctx_p, bool include_marks, os_ptr op1) |
| strlen(tname), (const byte *)tname); |
| break; |
| } |
| + case t_array: |
| + case t_shortarray: |
| + case t_mixedarray: |
| + if (!include_oparrays && errorexec_find(i_ctx_p, rq) < 0) |
| + make_null(rq); |
| + break; |
| default: |
| ; |
| } |
| @@ -841,14 +848,14 @@ execstack_continue(i_ctx_t *i_ctx_p) |
| { |
| os_ptr op = osp; |
| |
| - return do_execstack(i_ctx_p, false, op); |
| + return do_execstack(i_ctx_p, false, false, op); |
| } |
| static int |
| execstack2_continue(i_ctx_t *i_ctx_p) |
| { |
| os_ptr op = osp; |
| |
| - return do_execstack(i_ctx_p, op->value.boolval, op - 1); |
| + return do_execstack(i_ctx_p, op->value.boolval, true, op - 1); |
| } |
| |
| /* - .needinput - */ |
| -- |
| 2.7.4 |
| |