Blame SOURCES/ghostscript-cve-2018-19409.patch

a60c09
From 661e8d8fb8248c38d67958beda32f3a5876d0c3f Mon Sep 17 00:00:00 2001
a60c09
From: Chris Liddell <chris.liddell@artifex.com>
a60c09
Date: Wed, 14 Nov 2018 09:50:08 +0000
a60c09
Subject: [PATCH 1/4] Bug 700176: check the *output* device for
a60c09
 LockSafetyParams
a60c09
a60c09
When calling .setdevice we were checking if LockSafetyParams was set, and if so
a60c09
throwing an invalidaccess error.
a60c09
a60c09
The problem is, if another device, for example the pdf14 compositor is the 'top'
a60c09
device, that does not (and cannot) honour LockSafetyParams.
a60c09
a60c09
To solve this, we'll now use the (relatively new) gxdso_current_output_device
a60c09
spec_op to retrieve the *actual* output device, and check the LockSafetyParams
a60c09
flag in that.
a60c09
---
a60c09
 psi/zdevice.c | 12 ++++++++----
a60c09
 1 file changed, 8 insertions(+), 4 deletions(-)
a60c09
a60c09
diff --git a/psi/zdevice.c b/psi/zdevice.c
a60c09
index 8d48b74..c276746 100644
a60c09
--- a/psi/zdevice.c
a60c09
+++ b/psi/zdevice.c
a60c09
@@ -461,13 +461,17 @@ zputdeviceparams(i_ctx_t *i_ctx_p)
a60c09
 int
a60c09
 zsetdevice(i_ctx_t *i_ctx_p)
a60c09
 {
a60c09
-    gx_device *dev = gs_currentdevice(igs);
a60c09
+    gx_device *odev = NULL, *dev = gs_currentdevice(igs);
a60c09
     os_ptr op = osp;
a60c09
-    int code = 0;
a60c09
+    int code = dev_proc(dev, dev_spec_op)(dev,
a60c09
+                        gxdso_current_output_device, (void *)&odev, 0);
a60c09
+
a60c09
+    if (code < 0)
a60c09
+        return code;
a60c09
 
a60c09
     check_write_type(*op, t_device);
a60c09
-    if (dev->LockSafetyParams) {	  /* do additional checking if locked  */
a60c09
-        if(op->value.pdevice != dev) 	  /* don't allow a different device    */
a60c09
+    if (odev->LockSafetyParams) {	  /* do additional checking if locked  */
a60c09
+        if(op->value.pdevice != odev) 	  /* don't allow a different device    */
a60c09
             return_error(gs_error_invalidaccess);
a60c09
     }
a60c09
     dev->ShowpageCount = 0;
a60c09
-- 
a60c09
2.17.2
a60c09
a60c09
a60c09
From ea1b3ef437f39e45874f821c06bd953196625ac5 Mon Sep 17 00:00:00 2001
a60c09
From: Chris Liddell <chris.liddell@artifex.com>
a60c09
Date: Wed, 14 Nov 2018 21:04:46 +0000
a60c09
Subject: [PATCH 2/4] Bug 700176: Use the actual output device for both devices
a60c09
 in setdevice
a60c09
a60c09
Also fixes bug 700189.
a60c09
a60c09
The pdf14 compositor device, despite being a forwarding device, does not forward
a60c09
all spec_ops to it's target, only a select few are special cased for that.
a60c09
gxdso_current_output_device needs to be included in those special cases.
a60c09
a60c09
The original commit (661e8d8fb8248) changed the code to use the spec_op to
a60c09
retrieve the output device, checking that for LockSafetyParams. If
a60c09
LockSafetyParams is set, it returns an invalidaccess error if the new device
a60c09
differs from the current device.
a60c09
a60c09
When we do the comparison between the two devices, we need to check the
a60c09
output device in both cases.
a60c09
a60c09
This is complicated by the fact that the new device may not have ever been set
a60c09
(and thus fully initialised), and may not have a spec_op method available at
a60c09
that point.
a60c09
---
a60c09
 base/gdevp14.c |  3 ++-
a60c09
 psi/zdevice.c  | 18 ++++++++++++++++--
a60c09
 2 files changed, 18 insertions(+), 3 deletions(-)
a60c09
a60c09
diff --git a/base/gdevp14.c b/base/gdevp14.c
a60c09
index f89bc04..f47ed30 100644
a60c09
--- a/base/gdevp14.c
a60c09
+++ b/base/gdevp14.c
a60c09
@@ -5618,7 +5618,8 @@ pdf14_dev_spec_op(gx_device *pdev, int dev_spec_op,
a60c09
             return 0;
a60c09
         }
a60c09
     }
a60c09
-    if (dev_spec_op == gxdso_get_dev_param || dev_spec_op == gxdso_restrict_bbox) {
a60c09
+    if (dev_spec_op == gxdso_get_dev_param || dev_spec_op == gxdso_restrict_bbox
a60c09
+        || dev_spec_op == gxdso_current_output_device) {
a60c09
         return dev_proc(p14dev->target, dev_spec_op)(p14dev->target, dev_spec_op, data, size);
a60c09
     }
a60c09
 
a60c09
diff --git a/psi/zdevice.c b/psi/zdevice.c
a60c09
index c276746..4beda04 100644
a60c09
--- a/psi/zdevice.c
a60c09
+++ b/psi/zdevice.c
a60c09
@@ -462,16 +462,30 @@ int
a60c09
 zsetdevice(i_ctx_t *i_ctx_p)
a60c09
 {
a60c09
     gx_device *odev = NULL, *dev = gs_currentdevice(igs);
a60c09
+    gx_device *ndev = NULL;
a60c09
     os_ptr op = osp;
a60c09
     int code = dev_proc(dev, dev_spec_op)(dev,
a60c09
                         gxdso_current_output_device, (void *)&odev, 0);
a60c09
 
a60c09
     if (code < 0)
a60c09
         return code;
a60c09
-
a60c09
     check_write_type(*op, t_device);
a60c09
+
a60c09
+    /* slightly icky special case: the new device may not have had
a60c09
+     * it's procs initialised, at this point - but we need to check
a60c09
+     * whether we're being asked to change the device here
a60c09
+     */
a60c09
+    if (dev_proc((op->value.pdevice), dev_spec_op) == NULL)
a60c09
+        ndev = op->value.pdevice;
a60c09
+    else
a60c09
+        code = dev_proc((op->value.pdevice), dev_spec_op)(op->value.pdevice,
a60c09
+                        gxdso_current_output_device, (void *)&ndev, 0);
a60c09
+
a60c09
+    if (code < 0)
a60c09
+        return code;
a60c09
+
a60c09
     if (odev->LockSafetyParams) {	  /* do additional checking if locked  */
a60c09
-        if(op->value.pdevice != odev) 	  /* don't allow a different device    */
a60c09
+        if(ndev != odev) 	  /* don't allow a different device    */
a60c09
             return_error(gs_error_invalidaccess);
a60c09
     }
a60c09
     dev->ShowpageCount = 0;
a60c09
-- 
a60c09
2.17.2
a60c09
a60c09
a60c09
From 7c3e7eee829cc3d2582e4aa7ae1fd495ca72cef1 Mon Sep 17 00:00:00 2001
a60c09
From: Chris Liddell <chris.liddell@artifex.com>
a60c09
Date: Mon, 17 Sep 2018 14:06:12 +0100
a60c09
Subject: [PATCH 3/4] Implement .currentoutputdevice operator
a60c09
a60c09
The currentdevice operator returns the device currently installed in the
a60c09
graphics state. This can be the output/page device, but also could be a
a60c09
forwarding device (bbox device), compositor (pdf14) or subclass device
a60c09
(erasepage optimisation, First/Last page etc).
a60c09
a60c09
In certain circumstances (for example during a setpagedevice) we want to be
a60c09
sure we're retrieving the *actual* output/page device.
a60c09
a60c09
The new .currentoutputdevice operator uses the spec_op device method to traverse
a60c09
any chain of devices and retrieve the final device in the chain, which
a60c09
should always be the output/page device.
a60c09
---
a60c09
 Resource/Init/gs_init.ps  |  2 +-
a60c09
 Resource/Init/gs_setpd.ps |  8 +++++++-
a60c09
 base/gdevdflt.c           |  5 +++++
a60c09
 base/gxdevsop.h           |  4 ++++
a60c09
 psi/zdevice.c             | 30 ++++++++++++++++++++++++++++++
a60c09
 5 files changed, 47 insertions(+), 2 deletions(-)
a60c09
a60c09
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
a60c09
index bec307d..55d6923 100644
a60c09
--- a/Resource/Init/gs_init.ps
a60c09
+++ b/Resource/Init/gs_init.ps
a60c09
@@ -2211,7 +2211,7 @@ SAFER { .setsafeglobal } if
a60c09
   /.shfill /.argindex /.bytestring /.namestring /.stringbreak /.stringmatch /.globalvmarray /.globalvmdict /.globalvmpackedarray /.globalvmstring
a60c09
   /.localvmarray /.localvmdict /.localvmpackedarray /.localvmstring /.systemvmarray /.systemvmdict /.systemvmpackedarray /.systemvmstring /.systemvmfile /.systemvmlibfile
a60c09
   /.systemvmSFD /.settrapparams /.currentsystemparams /.currentuserparams /.getsystemparam /.getuserparam /.setsystemparams /.setuserparams
a60c09
-  /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath
a60c09
+  /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath /.currentoutputdevice
a60c09
 
a60c09
   % Used by a free user in the Library of Congress. Apparently this is used to
a60c09
   % draw a partial page, which is then filled in by the results of a barcode
a60c09
diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
a60c09
index 8fa7c51..aa79b3f 100644
a60c09
--- a/Resource/Init/gs_setpd.ps
a60c09
+++ b/Resource/Init/gs_setpd.ps
a60c09
@@ -877,7 +877,13 @@ SETPDDEBUG { (Selecting.) = pstack flush } if
a60c09
                 % Stack: mark <orig> <request> <merged> <failed>
a60c09
 SETPDDEBUG { (Constructing.) = pstack flush } if
a60c09
 
a60c09
-   currentdevice .devicename 2 index /OutputDevice get eq
a60c09
+   % Non-obvious: we need to check the name of the output device, to tell
a60c09
+   % whether we're going to have to replace the entire device chain (which
a60c09
+   % may be only one device, or may be multiple devices.
a60c09
+   % If we're not replacing the entire change, we have to use the device in
a60c09
+   % the graphics state, so the configuration of the entire device chain is
a60c09
+   % correctly set.
a60c09
+   .currentoutputdevice .devicename 2 index /OutputDevice get eq
a60c09
     { currentdevice }
a60c09
     { 1 index /OutputDevice get finddevice }
a60c09
    ifelse
a60c09
diff --git a/base/gdevdflt.c b/base/gdevdflt.c
a60c09
index 3cb9fbd..b5bd82b 100644
a60c09
--- a/base/gdevdflt.c
a60c09
+++ b/base/gdevdflt.c
a60c09
@@ -1044,6 +1044,11 @@ gx_default_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size)
a60c09
                 dev_param_req_t *request = (dev_param_req_t *)data;
a60c09
                 return gx_default_get_param(pdev, request->Param, request->list);
a60c09
             }
a60c09
+        case gxdso_current_output_device:
a60c09
+            {
a60c09
+                *(gx_device **)data = pdev;
a60c09
+                return 0;
a60c09
+            }
a60c09
     }
a60c09
     return_error(gs_error_undefined);
a60c09
 }
a60c09
diff --git a/base/gxdevsop.h b/base/gxdevsop.h
a60c09
index cd3b632..27e3e84 100644
a60c09
--- a/base/gxdevsop.h
a60c09
+++ b/base/gxdevsop.h
a60c09
@@ -327,6 +327,10 @@ enum {
a60c09
     gxdso_JPEG_passthrough_data,
a60c09
     gxdso_JPEG_passthrough_end,
a60c09
     gxdso_supports_iccpostrender,
a60c09
+    /* Retrieve the last device in a device chain
a60c09
+       (either forwarding or subclass devices).
a60c09
+     */
a60c09
+    gxdso_current_output_device,
a60c09
     /* Add new gxdso_ keys above this. */
a60c09
     gxdso_pattern__LAST
a60c09
 };
a60c09
diff --git a/psi/zdevice.c b/psi/zdevice.c
a60c09
index 4beda04..03285dc 100644
a60c09
--- a/psi/zdevice.c
a60c09
+++ b/psi/zdevice.c
a60c09
@@ -57,6 +57,7 @@ zcopydevice2(i_ctx_t *i_ctx_p)
a60c09
 }
a60c09
 
a60c09
 /* - currentdevice <device> */
a60c09
+/* Returns the current device in the graphics state */
a60c09
 int
a60c09
 zcurrentdevice(i_ctx_t *i_ctx_p)
a60c09
 {
a60c09
@@ -71,6 +72,34 @@ zcurrentdevice(i_ctx_t *i_ctx_p)
a60c09
     return 0;
a60c09
 }
a60c09
 
a60c09
+/* - .currentoutputdevice <device> */
a60c09
+/* Returns the *output* device - which will often
a60c09
+   be the same as above, but not always: if a compositor
a60c09
+   or other forwarding device, or subclassing device is
a60c09
+   in force, that will be referenced by the graphics state
a60c09
+   rather than the output device.
a60c09
+   This is equivalent of currentdevice device, but returns
a60c09
+   the *device* object, rather than the dictionary describing
a60c09
+   the device and device state.
a60c09
+ */
a60c09
+static int
a60c09
+zcurrentoutputdevice(i_ctx_t *i_ctx_p)
a60c09
+{
a60c09
+    os_ptr op = osp;
a60c09
+    gx_device *odev = NULL, *dev = gs_currentdevice(igs);
a60c09
+    gs_ref_memory_t *mem = (gs_ref_memory_t *) dev->memory;
a60c09
+    int code = dev_proc(dev, dev_spec_op)(dev,
a60c09
+                        gxdso_current_output_device, (void *)&odev, 0);
a60c09
+    if (code < 0)
a60c09
+        return code;
a60c09
+
a60c09
+    push(1);
a60c09
+    make_tav(op, t_device,
a60c09
+             (mem == 0 ? avm_foreign : imemory_space(mem)) | a_all,
a60c09
+             pdevice, odev);
a60c09
+    return 0;
a60c09
+}
a60c09
+
a60c09
 /* <device> .devicename <string> */
a60c09
 static int
a60c09
 zdevicename(i_ctx_t *i_ctx_p)
a60c09
@@ -632,6 +661,7 @@ const op_def zdevice_op_defs[] =
a60c09
 {
a60c09
     {"1.copydevice2", zcopydevice2},
a60c09
     {"0currentdevice", zcurrentdevice},
a60c09
+    {"0.currentoutputdevice", zcurrentoutputdevice},
a60c09
     {"1.devicename", zdevicename},
a60c09
     {"0.doneshowpage", zdoneshowpage},
a60c09
     {"0flushpage", zflushpage},
a60c09
-- 
a60c09
2.17.2
a60c09
a60c09
a60c09
From 4d98293c72cc5b5fe456065a3252d39e9ab28e4d Mon Sep 17 00:00:00 2001
a60c09
From: Ken Sharp <ken.sharp@artifex.com>
a60c09
Date: Mon, 19 Nov 2018 09:00:54 +0000
a60c09
Subject: [PATCH 4/4] Coverity ID 327264 - move pointer NULL check
a60c09
a60c09
Due to recent changes in this code, the pointer was being dereferenced
a60c09
before we checked it to see if it was NULL. Moe the check so that we
a60c09
check for NULL before dereferencing.
a60c09
a60c09
The 'pvalue' of the operand can be NULL, even if the object is a t_device
a60c09
type, because invalidate_stack_devices traverses the operand stack
a60c09
looking for devices, and sets their pvalue member to NULL in order to
a60c09
invalidate them so that they cannot be used.
a60c09
---
a60c09
 psi/zdevice.c | 6 +++---
a60c09
 1 file changed, 3 insertions(+), 3 deletions(-)
a60c09
a60c09
diff --git a/psi/zdevice.c b/psi/zdevice.c
a60c09
index 03285dc..63865f1 100644
a60c09
--- a/psi/zdevice.c
a60c09
+++ b/psi/zdevice.c
a60c09
@@ -500,6 +500,9 @@ zsetdevice(i_ctx_t *i_ctx_p)
a60c09
         return code;
a60c09
     check_write_type(*op, t_device);
a60c09
 
a60c09
+    if (op->value.pdevice == 0)
a60c09
+        return gs_note_error(gs_error_undefined);
a60c09
+
a60c09
     /* slightly icky special case: the new device may not have had
a60c09
      * it's procs initialised, at this point - but we need to check
a60c09
      * whether we're being asked to change the device here
a60c09
@@ -519,9 +522,6 @@ zsetdevice(i_ctx_t *i_ctx_p)
a60c09
     }
a60c09
     dev->ShowpageCount = 0;
a60c09
 
a60c09
-    if (op->value.pdevice == 0)
a60c09
-        return gs_note_error(gs_error_undefined);
a60c09
-
a60c09
     code = gs_setdevice_no_erase(igs, op->value.pdevice);
a60c09
     if (code < 0)
a60c09
         return code;
a60c09
-- 
a60c09
2.17.2
a60c09