From f6b11ea745395193f4f1fc8a7b09dda9913dbe72 Mon Sep 17 00:00:00 2001 From: Chris Liddell Date: Fri, 7 Sep 2018 14:23:06 +0100 Subject: Bug 699740: Better handle failing to set the nulldevice When pushing the nulldevice, if gs_setdevice_no_erase() failed, that *could* mean we end up freeing the device referenced in the graphics state. If that happens, search back through the saved gstates to find the initial graphics state, and pull the initial device from there. This allows us to return a Fatal error code, and exit cleanly. --- base/gsdevice.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'base/gsdevice.c') diff --git a/base/gsdevice.c b/base/gsdevice.c index e0cf1058c..5f298be16 100644 --- a/base/gsdevice.c +++ b/base/gsdevice.c @@ -695,8 +695,9 @@ int gs_nulldevice(gs_gstate * pgs) { int code = 0; + gs_gstate *spgs; bool saveLockSafety = false; - if (pgs->device == 0 || !gx_device_is_null(pgs->device)) { + if (pgs->device == NULL || !gx_device_is_null(pgs->device)) { gx_device *ndev; code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device, pgs->memory); @@ -722,10 +723,20 @@ gs_nulldevice(gs_gstate * pgs) set_dev_proc(ndev, get_profile, gx_default_get_profile); } - if ((code = gs_setdevice_no_erase(pgs, ndev)) < 0) + if (gs_setdevice_no_erase(pgs, ndev) < 0) { gs_free_object(pgs->memory, ndev, "gs_copydevice(device)"); - if (pgs->device != NULL) - pgs->device->LockSafetyParams = saveLockSafety; + /* We are out of options: find the device we installed in + the initial graphics state, and put that in place. + We just need something so we can end this job cleanly. + */ + spgs = pgs->saved; + while (spgs->saved) spgs = spgs->saved; + gs_currentdevice_inline(pgs) = gs_currentdevice_inline(spgs); + rc_increment(gs_currentdevice_inline(pgs)); + code = gs_note_error(gs_error_Fatal); + } + if (gs_currentdevice_inline(pgs) != NULL) + gs_currentdevice_inline(pgs)->LockSafetyParams = saveLockSafety; } return code; } -- cgit v1.2.1