Blob Blame History Raw
From: Chris Liddell <chris.liddell@artifex.com>
Date: Thu, 23 Aug 2018 14:41:18 +0000 (+0100)
Subject: Bug 699664: Ensure the correct is in place before cleanup

Bug 699664: Ensure the correct is in place before cleanup

If the PS job replaces the device and leaves that graphics state in place, we
wouldn't cleanup the default device in the normal way, but rely on the garbage
collector.

This works (but isn't ideal), *except* when the job replaces the device with
the null device (using the nulldevice operator) - this means that
.uninstallpagedevice doesn't replace the existing device with the nulldevice
(since it is already installed), the device from the graphics ends up being
freed - and as it is the nulldevice, which we rely on, memory corruption
and a segfault can happen.

We avoid this by checking if the current device is the nulldevice, and if so,
restoring it away, before continuing with the device cleanup.

http://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=241d91112771a6104de10b3948c3f350d6690c1d
---

diff -up ghostscript-9.07/psi/imain.c.cve-2018-16541 ghostscript-9.07/psi/imain.c
--- ghostscript-9.07/psi/imain.c.cve-2018-16541	2018-11-29 15:54:54.640496328 +0100
+++ ghostscript-9.07/psi/imain.c	2018-11-29 15:56:00.652563801 +0100
@@ -846,6 +846,16 @@ gs_main_finit(gs_main_instance * minst,
             i_ctx_p = minst->i_ctx_p; /* interp_reclaim could change it. */
         }
 #ifndef PSI_INCLUDED
+        if (i_ctx_p->pgs != NULL && i_ctx_p->pgs->device != NULL &&
+            gx_device_is_null(i_ctx_p->pgs->device)) {
+            /* if the job replaced the device with the nulldevice, we we need to grestore
+               away that device, so the block below can properly dispense
+               with the default device.
+             */
+            int code = gs_grestoreall(i_ctx_p->pgs);
+            if (code < 0) return_error(gs_error_Fatal);
+        }
+
         if (i_ctx_p->pgs != NULL && i_ctx_p->pgs->device != NULL) {
             gx_device *pdev = i_ctx_p->pgs->device;
             const char * dname = pdev->dname;