Fix CVE-2017-8291:

https://bugs.ghostscript.com/show_bug.cgi?id=697799
https://bugs.ghostscript.com/show_bug.cgi?id=697808 (duplicate)
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8291

Patches copied from upstream source repository:

https://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=4f83478c88c2e05d6e8d79ca4557eb039354d2f3
https://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=04b37bbce174eed24edec7ad5b920eb93db4d47d
https://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=57f20719e1cfaea77b67cb26e26de7fe4d7f9b2e
https://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=ccfd2c75ac9be4cbd369e4cbdd40ba11a0c7bdad

From 4f83478c88c2e05d6e8d79ca4557eb039354d2f3 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Thu, 27 Apr 2017 13:03:33 +0100
Subject: [PATCH] Bug 697799: have .eqproc check its parameters

The Ghostscript custom operator .eqproc was not check the number or type of
the parameters it was given.
---
 psi/zmisc3.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/psi/zmisc3.c b/psi/zmisc3.c
index 54b304246..37293ff4b 100644
--- a/psi/zmisc3.c
+++ b/psi/zmisc3.c
@@ -56,6 +56,12 @@ zeqproc(i_ctx_t *i_ctx_p)
     ref2_t stack[MAX_DEPTH + 1];
     ref2_t *top = stack;
 
+    if (ref_stack_count(&o_stack) < 2)
+        return_error(gs_error_stackunderflow);
+    if (!r_is_array(op - 1) || !r_is_array(op)) {
+        return_error(gs_error_typecheck);
+    }
+
     make_array(&stack[0].proc1, 0, 1, op - 1);
     make_array(&stack[0].proc2, 0, 1, op);
     for (;;) {
-- 
2.13.0

From 04b37bbce174eed24edec7ad5b920eb93db4d47d Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Thu, 27 Apr 2017 13:21:31 +0100
Subject: [PATCH] Bug 697799: have .rsdparams check its parameters

The Ghostscript internal operator .rsdparams wasn't checking the number or
type of the operands it was being passed. Do so.
---
 psi/zfrsd.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/psi/zfrsd.c b/psi/zfrsd.c
index 191107d8a..950588d69 100644
--- a/psi/zfrsd.c
+++ b/psi/zfrsd.c
@@ -49,13 +49,20 @@ zrsdparams(i_ctx_t *i_ctx_p)
     ref *pFilter;
     ref *pDecodeParms;
     int Intent = 0;
-    bool AsyncRead;
+    bool AsyncRead = false;
     ref empty_array, filter1_array, parms1_array;
     uint i;
-    int code;
+    int code = 0;
+
+    if (ref_stack_count(&o_stack) < 1)
+        return_error(gs_error_stackunderflow);
+    if (!r_has_type(op, t_dictionary) && !r_has_type(op, t_null)) {
+        return_error(gs_error_typecheck);
+    }
 
     make_empty_array(&empty_array, a_readonly);
-    if (dict_find_string(op, "Filter", &pFilter) > 0) {
+    if (r_has_type(op, t_dictionary)
+        && dict_find_string(op, "Filter", &pFilter) > 0) {
         if (!r_is_array(pFilter)) {
             if (!r_has_type(pFilter, t_name))
                 return_error(gs_error_typecheck);
@@ -94,12 +101,13 @@ zrsdparams(i_ctx_t *i_ctx_p)
                 return_error(gs_error_typecheck);
         }
     }
-    code = dict_int_param(op, "Intent", 0, 3, 0, &Intent);
+    if (r_has_type(op, t_dictionary))
+        code = dict_int_param(op, "Intent", 0, 3, 0, &Intent);
     if (code < 0 && code != gs_error_rangecheck) /* out-of-range int is ok, use 0 */
         return code;
-    if ((code = dict_bool_param(op, "AsyncRead", false, &AsyncRead)) < 0
-        )
-        return code;
+    if (r_has_type(op, t_dictionary))
+        if ((code = dict_bool_param(op, "AsyncRead", false, &AsyncRead)) < 0)
+            return code;
     push(1);
     op[-1] = *pFilter;
     if (pDecodeParms)
-- 
2.13.0

From 57f20719e1cfaea77b67cb26e26de7fe4d7f9b2e Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Wed, 3 May 2017 12:05:45 +0100
Subject: [PATCH] Bug 697846: revision to commit 4f83478c88 (.eqproc)

When using the "DELAYBIND" feature, it turns out that .eqproc can be called with
parameters that are not both procedures. In this case, it turns out, the
expectation is for the operator to return 'false', rather than throw an error.
---
 psi/zmisc3.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/psi/zmisc3.c b/psi/zmisc3.c
index 37293ff4b..3f01d39a3 100644
--- a/psi/zmisc3.c
+++ b/psi/zmisc3.c
@@ -38,6 +38,15 @@ zcliprestore(i_ctx_t *i_ctx_p)
     return gs_cliprestore(igs);
 }
 
+static inline bool
+eqproc_check_type(ref *r)
+{
+    return r_has_type(r, t_array)
+           || r_has_type(r, t_mixedarray)
+           || r_has_type(r, t_shortarray)
+           || r_has_type(r, t_oparray);
+}
+
 /* <proc1> <proc2> .eqproc <bool> */
 /*
  * Test whether two procedures are equal to depth 10.
@@ -58,8 +67,10 @@ zeqproc(i_ctx_t *i_ctx_p)
 
     if (ref_stack_count(&o_stack) < 2)
         return_error(gs_error_stackunderflow);
-    if (!r_is_array(op - 1) || !r_is_array(op)) {
-        return_error(gs_error_typecheck);
+    if (!eqproc_check_type(op -1) || !eqproc_check_type(op)) {
+        make_false(op - 1);
+        pop(1);
+        return 0;
     }
 
     make_array(&stack[0].proc1, 0, 1, op - 1);
-- 
2.13.0

From ccfd2c75ac9be4cbd369e4cbdd40ba11a0c7bdad Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Thu, 11 May 2017 14:07:48 +0100
Subject: [PATCH] Bug 697892: fix check for op stack underflow.

In the original fix, I used the wrong method to check for stack underflow, this
is using the correct method.
---
 psi/zfrsd.c  | 3 +--
 psi/zmisc3.c | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/psi/zfrsd.c b/psi/zfrsd.c
index 950588d69..9c035b96d 100644
--- a/psi/zfrsd.c
+++ b/psi/zfrsd.c
@@ -54,8 +54,7 @@ zrsdparams(i_ctx_t *i_ctx_p)
     uint i;
     int code = 0;
 
-    if (ref_stack_count(&o_stack) < 1)
-        return_error(gs_error_stackunderflow);
+    check_op(1);
     if (!r_has_type(op, t_dictionary) && !r_has_type(op, t_null)) {
         return_error(gs_error_typecheck);
     }
diff --git a/psi/zmisc3.c b/psi/zmisc3.c
index 3f01d39a3..43803b55b 100644
--- a/psi/zmisc3.c
+++ b/psi/zmisc3.c
@@ -65,8 +65,7 @@ zeqproc(i_ctx_t *i_ctx_p)
     ref2_t stack[MAX_DEPTH + 1];
     ref2_t *top = stack;
 
-    if (ref_stack_count(&o_stack) < 2)
-        return_error(gs_error_stackunderflow);
+    check_op(2);
     if (!eqproc_check_type(op -1) || !eqproc_check_type(op)) {
         make_false(op - 1);
         pop(1);
-- 
2.13.0

