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

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