Sophie

Sophie

distrib > Mageia > 6 > armv7hl > media > core-updates-src > by-pkgid > bc219369320b6b5781eed48254462cef > files > 11

ghostscript-9.25-1.2.mga6.src.rpm

From 3c218c1463b9c2ff39b1ea514824815fde4853a7 Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Tue, 16 Oct 2018 11:21:22 +0100
Subject: [PATCH] Bug 699962: Ensure device survives Postscript "callout"

In shutting down the interpreter, we run Postscript code to remove the 'real'
device from the graphics state (replacing it with the nulldevice). That means
we can shutdown and free the device in the C code, without impacting the
remaining interpreter shutdown.

There is, however, a very small chance that, whilst running the Postcript code,
the interpreter will trigger a garbage collection - if that happens *after*
the device reference has been removed from the graphics state, there is no
'link' to the device object for the garbager to follow. Thus the device can
be freed before control returns from executing the Postscript.

Register the device as a garbage collector 'root': thus it is implicitly marked
and won't be freed before control returns.
---
 psi/imain.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/psi/imain.c b/psi/imain.c
index f8fae98..a4a9917 100644
--- a/psi/imain.c
+++ b/psi/imain.c
@@ -956,6 +956,16 @@ gs_main_finit(gs_main_instance * minst, int exit_status, int code)
         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;
+            gs_gc_root_t dev_root;
+            /* There is a chance that, during the call to gs_main_run_string(), the interpreter may
+             * decide to call the garbager - the device is in gc memory, and the only reference to it
+             * (in the gstate) has been removed, thus it can be destroyed by the garbager.
+             * Counter-intuitively, adjusting the reference count makes not difference to that.
+             * Register the device as a gc 'root' so it will be implicitely marked by garbager, and
+             * and thus surive until control returns here.
+             */
+            if (gs_register_struct_root(pdev->memory, &dev_root, (void **)&pdev, "gs_main_finit") < 0)
+                return_error(gs_error_Fatal);
 
             /* make sure device doesn't isn't freed by .uninstalldevice */
             rc_adjust(pdev, 1, "gs_main_finit");
@@ -978,6 +988,7 @@ gs_main_finit(gs_main_instance * minst, int exit_status, int code)
                     emprintf2(imemory, "UNKNOWN ERROR %d closing %s device.\n", code, dname);
                }
             }
+            gs_unregister_root(pdev->memory, &dev_root, "gs_main_finit");
             rc_decrement(pdev, "gs_main_finit");                /* device might be freed */
             if (exit_status == 0 || exit_status == gs_error_Quit)
                 exit_status = code;
-- 
2.9.1