diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2018-09-07 15:22:29 +0100 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2018-09-07 15:34:58 +0100 |
commit | 65a9046ded8e9edd5d33bc812a9e94ae29607a1e (patch) | |
tree | 2195c2b596572e0bbe805f979272287b9b284f81 | |
parent | 0da9680ca0506fd3cdf70840ad5387d85cab4996 (diff) |
Bug #699707 "Security review bug - continuation procedures"
As a result of the recent security review, this bug was raised to go
through the PostScript interpreter looking for places where we exit the
'C' level and return control to PostScript. This is done when we need
to evaluate something in the PostScript environment, such as a transfer
function or a tint transform.
Because these functions are written in PostScript we need to run them
in the PostScript environment.
To do this we push the procedure (or at least 'a' procedure) onto the
exec stack and exit with an o_push_estack error. In many cases that's
all we need to do, but sometimes we want to return control back to the
'C' environment and, in some of those cases, we want to store some state
for the C code. We can't use the operand stack (because the PostScript
function will alter that) so we store stuff on the exec stack instead.
When we complete the C level, we should restore the exec stack, so if
we stored any state on it, we should remove it. Sometimes we were not
doing so if there was an error.
Generally this did not cause a problem, because in general on an error
we would stop. However if the error handler had been altered it was
possible we might carry on. 'Sometimes' that would mean we tried to
execute something which wasn't executable, and sometimes it might mean
that we tried to return to the C level, but without the expected
state on the exec stack.
This could lead to memory corruption and crashes.
This commit tries to find everywhere where we might end up leaving
extra items on the exec stack in the case of an error, and either
removes the required number of items from the exec stack or uses
whatever cleanup routine was established for the C code.
Its important to note that, in normal use, none of these could actually
cause a problem. This makes it hard to test. all the cases here I have
tested, though in many cases the only way I could produce an error was
by forcing an error return in the debugger. I suspect some error cases
simply aren't possible but its good practice to check the return codes
anyway, even if its only a theoretical problem.
-rw-r--r-- | psi/zalg.c | 5 | ||||
-rw-r--r-- | psi/zcie.c | 82 | ||||
-rw-r--r-- | psi/zcolor1.c | 9 | ||||
-rw-r--r-- | psi/zcontrol.c | 4 | ||||
-rw-r--r-- | psi/zfile.c | 8 | ||||
-rw-r--r-- | psi/zht1.c | 5 | ||||
-rw-r--r-- | psi/zht2.c | 5 | ||||
-rw-r--r-- | psi/zpath1.c | 2 | ||||
-rw-r--r-- | psi/zpcolor.c | 12 |
9 files changed, 86 insertions, 46 deletions
diff --git a/psi/zalg.c b/psi/zalg.c index e2400d93d..2677e62c4 100644 --- a/psi/zalg.c +++ b/psi/zalg.c | |||
@@ -165,8 +165,10 @@ H6: H = 6; | |||
165 | ref_assign(&op[0], &Rn[j]); | 165 | ref_assign(&op[0], &Rn[j]); |
166 | break; | 166 | break; |
167 | case 6: | 167 | case 6: |
168 | /*H6_cont:*/if (!r_has_type(&op[0], t_boolean)) | 168 | /*H6_cont:*/if (!r_has_type(&op[0], t_boolean)) { |
169 | esp -= 9; | ||
169 | return_error(gs_error_typecheck); | 170 | return_error(gs_error_typecheck); |
171 | } | ||
170 | if (op[0].value.boolval) { | 172 | if (op[0].value.boolval) { |
171 | /* H7: */ ref_assign_old(&arry, &Rn[i], &Rn[j], ".sort(H7)"); | 173 | /* H7: */ ref_assign_old(&arry, &Rn[i], &Rn[j], ".sort(H7)"); |
172 | goto H4; | 174 | goto H4; |
@@ -176,6 +178,7 @@ H8: ref_assign_old(&arry, &Rn[i], &R, ".sort(H8)"); | |||
176 | } | 178 | } |
177 | default: | 179 | default: |
178 | pop(1); | 180 | pop(1); |
181 | esp -= 9; | ||
179 | return_error(gs_error_unregistered); /* Must not happen. */ | 182 | return_error(gs_error_unregistered); /* Must not happen. */ |
180 | } | 183 | } |
181 | esp += 2; | 184 | esp += 2; |
diff --git a/psi/zcie.c b/psi/zcie.c index c3c2cb4d0..efe2a2f63 100644 --- a/psi/zcie.c +++ b/psi/zcie.c | |||
@@ -455,25 +455,29 @@ ciedefgspace(i_ctx_t *i_ctx_p, ref *CIEDict, ulong dictkey) | |||
455 | push(1); /* Sacrificial */ | 455 | push(1); /* Sacrificial */ |
456 | procs = istate->colorspace[0].procs.cie; | 456 | procs = istate->colorspace[0].procs.cie; |
457 | if (pcs == NULL ) { | 457 | if (pcs == NULL ) { |
458 | if ((code = dict_find_string(CIEDict, "Table", &ptref)) <= 0) | 458 | if ((code = dict_find_string(CIEDict, "Table", &ptref)) <= 0) { |
459 | return (code < 0 ? code : gs_note_error(gs_error_rangecheck)); | 459 | if (code == 0) |
460 | check_read_type(*ptref, t_array); | 460 | gs_note_error(cie_set_finish(i_ctx_p, pcs, &procs, edepth, gs_error_rangecheck)); |
461 | if (r_size(ptref) != 5) | 461 | else |
462 | return_error(gs_error_rangecheck); | 462 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
463 | /* Stable memory due to current caching of color space */ | 463 | } |
464 | code = gs_cspace_build_CIEDEFG(&pcs, NULL, mem->stable_memory); | 464 | check_read_type(*ptref, t_array); |
465 | if (code < 0) | 465 | if (r_size(ptref) != 5) |
466 | return code; | 466 | return_error(gs_error_rangecheck); |
467 | pcie = pcs->params.defg; | 467 | /* Stable memory due to current caching of color space */ |
468 | pcie->Table.n = 4; | 468 | code = gs_cspace_build_CIEDEFG(&pcs, NULL, mem->stable_memory); |
469 | pcie->Table.m = 3; | 469 | if (code < 0) |
470 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); | ||
471 | pcie = pcs->params.defg; | ||
472 | pcie->Table.n = 4; | ||
473 | pcie->Table.m = 3; | ||
470 | code = cie_cache_push_finish(i_ctx_p, cie_defg_finish, imem, pcie); | 474 | code = cie_cache_push_finish(i_ctx_p, cie_defg_finish, imem, pcie); |
471 | if (code < 0) | 475 | if (code < 0) |
472 | return code; | 476 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
473 | code = cie_defg_param(i_ctx_p, imemory, CIEDict, pcie, &procs, | 477 | code = cie_defg_param(i_ctx_p, imemory, CIEDict, pcie, &procs, |
474 | &has_abc_procs, &has_lmn_procs, &has_defg_procs,ptref); | 478 | &has_abc_procs, &has_lmn_procs, &has_defg_procs,ptref); |
475 | if (code < 0) | 479 | if (code < 0) |
476 | return code; | 480 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
477 | /* Add the color space to the profile cache */ | 481 | /* Add the color space to the profile cache */ |
478 | gsicc_add_cs(igs, pcs,dictkey); | 482 | gsicc_add_cs(igs, pcs,dictkey); |
479 | } else { | 483 | } else { |
@@ -561,25 +565,29 @@ ciedefspace(i_ctx_t *i_ctx_p, ref *CIEDict, ulong dictkey) | |||
561 | push(1); /* Sacrificial */ | 565 | push(1); /* Sacrificial */ |
562 | procs = istate->colorspace[0].procs.cie; | 566 | procs = istate->colorspace[0].procs.cie; |
563 | if (pcs == NULL ) { | 567 | if (pcs == NULL ) { |
564 | if ((code = dict_find_string(CIEDict, "Table", &ptref)) <= 0) | 568 | if ((code = dict_find_string(CIEDict, "Table", &ptref)) <= 0) { |
565 | return (code < 0 ? code : gs_note_error(gs_error_rangecheck)); | 569 | if (code == 0) |
566 | check_read_type(*ptref, t_array); | 570 | gs_note_error(cie_set_finish(i_ctx_p, pcs, &procs, edepth, gs_error_rangecheck)); |
567 | if (r_size(ptref) != 4) | 571 | else |
568 | return_error(gs_error_rangecheck); | 572 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
569 | /* Stable memory due to current caching of color space */ | 573 | } |
570 | code = gs_cspace_build_CIEDEF(&pcs, NULL, mem->stable_memory); | 574 | check_read_type(*ptref, t_array); |
571 | if (code < 0) | 575 | if (r_size(ptref) != 4) |
572 | return code; | 576 | return_error(gs_error_rangecheck); |
573 | pcie = pcs->params.def; | 577 | /* Stable memory due to current caching of color space */ |
574 | pcie->Table.n = 3; | 578 | code = gs_cspace_build_CIEDEF(&pcs, NULL, mem->stable_memory); |
575 | pcie->Table.m = 3; | 579 | if (code < 0) |
580 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); | ||
581 | pcie = pcs->params.def; | ||
582 | pcie->Table.n = 3; | ||
583 | pcie->Table.m = 3; | ||
576 | code = cie_cache_push_finish(i_ctx_p, cie_def_finish, imem, pcie); | 584 | code = cie_cache_push_finish(i_ctx_p, cie_def_finish, imem, pcie); |
577 | if (code < 0) | 585 | if (code < 0) |
578 | return code; | 586 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
579 | code = cie_def_param(i_ctx_p, imemory, CIEDict, pcie, &procs, | 587 | code = cie_def_param(i_ctx_p, imemory, CIEDict, pcie, &procs, |
580 | &has_abc_procs, &has_lmn_procs, &has_def_procs, ptref); | 588 | &has_abc_procs, &has_lmn_procs, &has_def_procs, ptref); |
581 | if (code < 0) | 589 | if (code < 0) |
582 | return code; | 590 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
583 | /* Add the color space to the profile cache */ | 591 | /* Add the color space to the profile cache */ |
584 | gsicc_add_cs(igs, pcs,dictkey); | 592 | gsicc_add_cs(igs, pcs,dictkey); |
585 | } else { | 593 | } else { |
@@ -629,15 +637,15 @@ cieabcspace(i_ctx_t *i_ctx_p, ref *CIEDict, ulong dictkey) | |||
629 | /* Stable memory due to current caching of color space */ | 637 | /* Stable memory due to current caching of color space */ |
630 | code = gs_cspace_build_CIEABC(&pcs, NULL, mem->stable_memory); | 638 | code = gs_cspace_build_CIEABC(&pcs, NULL, mem->stable_memory); |
631 | if (code < 0) | 639 | if (code < 0) |
632 | return code; | 640 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
633 | pcie = pcs->params.abc; | 641 | pcie = pcs->params.abc; |
634 | code = cie_cache_push_finish(i_ctx_p, cie_abc_finish, imem, pcie); | 642 | code = cie_cache_push_finish(i_ctx_p, cie_abc_finish, imem, pcie); |
635 | if (code < 0) | 643 | if (code < 0) |
636 | return code; | 644 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
637 | code = cie_abc_param(i_ctx_p, imemory, CIEDict, pcie, &procs, | 645 | code = cie_abc_param(i_ctx_p, imemory, CIEDict, pcie, &procs, |
638 | &has_abc_procs, &has_lmn_procs); | 646 | &has_abc_procs, &has_lmn_procs); |
639 | if (code < 0) | 647 | if (code < 0) |
640 | return code; | 648 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
641 | /* Set the color space in the graphic state. The ICC profile | 649 | /* Set the color space in the graphic state. The ICC profile |
642 | will be set later if we actually use the space. Procs will be | 650 | will be set later if we actually use the space. Procs will be |
643 | sampled now though. Also, the finish procedure is on the stack | 651 | sampled now though. Also, the finish procedure is on the stack |
@@ -692,16 +700,16 @@ cieaspace(i_ctx_t *i_ctx_p, ref *CIEdict, ulong dictkey) | |||
692 | /* Stable memory due to current caching of color space */ | 700 | /* Stable memory due to current caching of color space */ |
693 | code = gs_cspace_build_CIEA(&pcs, NULL, mem->stable_memory); | 701 | code = gs_cspace_build_CIEA(&pcs, NULL, mem->stable_memory); |
694 | if (code < 0) | 702 | if (code < 0) |
695 | return code; | 703 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
696 | pcie = pcs->params.a; | 704 | pcie = pcs->params.a; |
697 | code = cie_a_param(imemory, CIEdict, pcie, &procs, &has_a_procs, | 705 | code = cie_a_param(imemory, CIEdict, pcie, &procs, &has_a_procs, |
698 | &has_lmn_procs); | 706 | &has_lmn_procs); |
699 | if (code < 0) | 707 | if (code < 0) |
700 | return code; | 708 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
701 | /* Push finalize procedure on the execution stack */ | 709 | /* Push finalize procedure on the execution stack */ |
702 | code = cie_cache_push_finish(i_ctx_p, cie_a_finish, (gs_ref_memory_t *)imem, pcie); | 710 | code = cie_cache_push_finish(i_ctx_p, cie_a_finish, (gs_ref_memory_t *)imem, pcie); |
703 | if (code < 0) | 711 | if (code < 0) |
704 | return code; | 712 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
705 | if (!has_a_procs && !has_lmn_procs) { | 713 | if (!has_a_procs && !has_lmn_procs) { |
706 | pcie->common.caches.DecodeLMN->floats | 714 | pcie->common.caches.DecodeLMN->floats |
707 | .params.is_identity = true; | 715 | .params.is_identity = true; |
@@ -713,7 +721,7 @@ cieaspace(i_ctx_t *i_ctx_p, ref *CIEdict, ulong dictkey) | |||
713 | code = cie_prepare_iccproc(i_ctx_p, &pcie->RangeA, | 721 | code = cie_prepare_iccproc(i_ctx_p, &pcie->RangeA, |
714 | &procs.Decode.A, &pcie->caches.DecodeA.floats, pcie, imem, "Decode.A"); | 722 | &procs.Decode.A, &pcie->caches.DecodeA.floats, pcie, imem, "Decode.A"); |
715 | if (code < 0) | 723 | if (code < 0) |
716 | return code; | 724 | return cie_set_finish(i_ctx_p, pcs, &procs, edepth, code); |
717 | } else { | 725 | } else { |
718 | pcie->caches.DecodeA.floats.params.is_identity = true; | 726 | pcie->caches.DecodeA.floats.params.is_identity = true; |
719 | } | 727 | } |
@@ -842,8 +850,10 @@ cie_cache_finish_store(i_ctx_t *i_ctx_p, bool replicate) | |||
842 | code = float_param(ref_stack_index(&o_stack, | 850 | code = float_param(ref_stack_index(&o_stack, |
843 | (replicate ? 0 : gx_cie_cache_size - 1 - i)), | 851 | (replicate ? 0 : gx_cie_cache_size - 1 - i)), |
844 | &pcache->values[i]); | 852 | &pcache->values[i]); |
845 | if (code < 0) | 853 | if (code < 0) { |
854 | esp -= 2; /* pop pointer to cache */ | ||
846 | return code; | 855 | return code; |
856 | } | ||
847 | } | 857 | } |
848 | } | 858 | } |
849 | #ifdef DEBUG | 859 | #ifdef DEBUG |
diff --git a/psi/zcolor1.c b/psi/zcolor1.c index 56dcf71d8..1a341ff41 100644 --- a/psi/zcolor1.c +++ b/psi/zcolor1.c | |||
@@ -94,6 +94,7 @@ static int | |||
94 | zsetcolortransfer(i_ctx_t *i_ctx_p) | 94 | zsetcolortransfer(i_ctx_t *i_ctx_p) |
95 | { | 95 | { |
96 | os_ptr op = osp; | 96 | os_ptr op = osp; |
97 | os_ptr ep = esp; | ||
97 | int code; | 98 | int code; |
98 | 99 | ||
99 | check_proc(op[-3]); | 100 | check_proc(op[-3]); |
@@ -130,8 +131,14 @@ zsetcolortransfer(i_ctx_t *i_ctx_p) | |||
130 | (code = zcolor_remap_one(i_ctx_p, &istate->transfer_procs.gray, | 131 | (code = zcolor_remap_one(i_ctx_p, &istate->transfer_procs.gray, |
131 | igs->set_transfer.gray, igs, | 132 | igs->set_transfer.gray, igs, |
132 | zcolor_remap_one_finish)) < 0 | 133 | zcolor_remap_one_finish)) < 0 |
133 | ) | 134 | ) |
135 | { | ||
136 | /* Return the exec stack to the state it was in before we started the setup | ||
137 | * for the transfer function evaluation. | ||
138 | */ | ||
139 | esp = ep; | ||
134 | return code; | 140 | return code; |
141 | } | ||
135 | return o_push_estack; | 142 | return o_push_estack; |
136 | } | 143 | } |
137 | 144 | ||
diff --git a/psi/zcontrol.c b/psi/zcontrol.c index ebcd5e385..36da22ca0 100644 --- a/psi/zcontrol.c +++ b/psi/zcontrol.c | |||
@@ -239,8 +239,10 @@ end_runandhide(i_ctx_t *i_ctx_p) | |||
239 | { | 239 | { |
240 | int code; | 240 | int code; |
241 | 241 | ||
242 | if ((code = runandhide_restore_hidden(i_ctx_p, esp, esp - 1)) < 0) | 242 | if ((code = runandhide_restore_hidden(i_ctx_p, esp, esp - 1)) < 0) { |
243 | esp -= 2; | ||
243 | return code; | 244 | return code; |
245 | } | ||
244 | esp -= 2; /* pop the hidden value and its atributes */ | 246 | esp -= 2; /* pop the hidden value and its atributes */ |
245 | return o_pop_estack; | 247 | return o_pop_estack; |
246 | } | 248 | } |
diff --git a/psi/zfile.c b/psi/zfile.c index b30784029..d6575ea86 100644 --- a/psi/zfile.c +++ b/psi/zfile.c | |||
@@ -425,8 +425,10 @@ file_continue(i_ctx_t *i_ctx_p) | |||
425 | uint len = r_size(pscratch); | 425 | uint len = r_size(pscratch); |
426 | uint code; | 426 | uint code; |
427 | 427 | ||
428 | if (len < devlen) | 428 | if (len < devlen) { |
429 | esp -= 5; /* pop proc, pfen, devlen, iodev , mark */ | ||
429 | return_error(gs_error_rangecheck); /* not even room for device len */ | 430 | return_error(gs_error_rangecheck); /* not even room for device len */ |
431 | } | ||
430 | 432 | ||
431 | do { | 433 | do { |
432 | memcpy((char *)pscratch->value.bytes, iodev->dname, devlen); | 434 | memcpy((char *)pscratch->value.bytes, iodev->dname, devlen); |
@@ -435,8 +437,10 @@ file_continue(i_ctx_t *i_ctx_p) | |||
435 | if (code == ~(uint) 0) { /* all done */ | 437 | if (code == ~(uint) 0) { /* all done */ |
436 | esp -= 5; /* pop proc, pfen, devlen, iodev , mark */ | 438 | esp -= 5; /* pop proc, pfen, devlen, iodev , mark */ |
437 | return o_pop_estack; | 439 | return o_pop_estack; |
438 | } else if (code > len) /* overran string */ | 440 | } else if (code > len) { /* overran string */ |
441 | esp -= 5; /* pop proc, pfen, devlen, iodev , mark */ | ||
439 | return_error(gs_error_rangecheck); | 442 | return_error(gs_error_rangecheck); |
443 | } | ||
440 | else if (iodev != iodev_default(imemory) | 444 | else if (iodev != iodev_default(imemory) |
441 | || (check_file_permissions(i_ctx_p, (char *)pscratch->value.bytes, code + devlen, iodev, "PermitFileReading")) == 0) { | 445 | || (check_file_permissions(i_ctx_p, (char *)pscratch->value.bytes, code + devlen, iodev, "PermitFileReading")) == 0) { |
442 | push(1); | 446 | push(1); |
diff --git a/psi/zht1.c b/psi/zht1.c index 86f32e858..7265abbcf 100644 --- a/psi/zht1.c +++ b/psi/zht1.c | |||
@@ -115,8 +115,11 @@ setcolorscreen_finish(i_ctx_t *i_ctx_p) | |||
115 | 115 | ||
116 | pdht->order = pdht->components[0].corder; | 116 | pdht->order = pdht->components[0].corder; |
117 | code = gx_ht_install(igs, r_ptr(esp - 1, gs_halftone), pdht); | 117 | code = gx_ht_install(igs, r_ptr(esp - 1, gs_halftone), pdht); |
118 | if (code < 0) | 118 | if (code < 0) { |
119 | esp -= 7; | ||
120 | setcolorscreen_cleanup(i_ctx_p); | ||
119 | return code; | 121 | return code; |
122 | } | ||
120 | istate->screen_procs.red = esp[-5]; | 123 | istate->screen_procs.red = esp[-5]; |
121 | istate->screen_procs.green = esp[-4]; | 124 | istate->screen_procs.green = esp[-4]; |
122 | istate->screen_procs.blue = esp[-3]; | 125 | istate->screen_procs.blue = esp[-3]; |
diff --git a/psi/zht2.c b/psi/zht2.c index 48d7dd3b8..60bd6567e 100644 --- a/psi/zht2.c +++ b/psi/zht2.c | |||
@@ -558,8 +558,11 @@ sethalftone_finish(i_ctx_t *i_ctx_p) | |||
558 | if (pdht->components) | 558 | if (pdht->components) |
559 | pdht->order = pdht->components[0].corder; | 559 | pdht->order = pdht->components[0].corder; |
560 | code = gx_ht_install(igs, r_ptr(esp - 1, gs_halftone), pdht); | 560 | code = gx_ht_install(igs, r_ptr(esp - 1, gs_halftone), pdht); |
561 | if (code < 0) | 561 | if (code < 0) { |
562 | esp -= 4; | ||
563 | sethalftone_cleanup(i_ctx_p); | ||
562 | return code; | 564 | return code; |
565 | } | ||
563 | istate->halftone = esp[-2]; | 566 | istate->halftone = esp[-2]; |
564 | esp -= 4; | 567 | esp -= 4; |
565 | sethalftone_cleanup(i_ctx_p); | 568 | sethalftone_cleanup(i_ctx_p); |
diff --git a/psi/zpath1.c b/psi/zpath1.c index e9eca1c44..b9fb2e593 100644 --- a/psi/zpath1.c +++ b/psi/zpath1.c | |||
@@ -232,6 +232,8 @@ path_continue(i_ctx_t *i_ctx_p) | |||
232 | path_cleanup(i_ctx_p); | 232 | path_cleanup(i_ctx_p); |
233 | return o_pop_estack; | 233 | return o_pop_estack; |
234 | default: /* error */ | 234 | default: /* error */ |
235 | esp -= 6; | ||
236 | path_cleanup(i_ctx_p); | ||
235 | return code; | 237 | return code; |
236 | case gs_pe_moveto: | 238 | case gs_pe_moveto: |
237 | esp[2] = esp[-4]; /* moveto proc */ | 239 | esp[2] = esp[-4]; /* moveto proc */ |
diff --git a/psi/zpcolor.c b/psi/zpcolor.c index fb601a303..3c3e29e21 100644 --- a/psi/zpcolor.c +++ b/psi/zpcolor.c | |||
@@ -351,8 +351,10 @@ pattern_paint_finish(i_ctx_t *i_ctx_p) | |||
351 | } | 351 | } |
352 | pinst = (gs_pattern1_instance_t *)gs_currentcolor(igs->saved)->pattern; | 352 | pinst = (gs_pattern1_instance_t *)gs_currentcolor(igs->saved)->pattern; |
353 | /* If pinst is NULL after all of that then we are not going to recover */ | 353 | /* If pinst is NULL after all of that then we are not going to recover */ |
354 | if (pinst == NULL) | 354 | if (pinst == NULL) { |
355 | esp -= 5; | ||
355 | return_error(gs_error_unknownerror); | 356 | return_error(gs_error_unknownerror); |
357 | } | ||
356 | } | 358 | } |
357 | pgs = igs; | 359 | pgs = igs; |
358 | 360 | ||
@@ -360,8 +362,10 @@ pattern_paint_finish(i_ctx_t *i_ctx_p) | |||
360 | if (pinst->is_clist) { | 362 | if (pinst->is_clist) { |
361 | /* Send the compositor command to close the PDF14 device */ | 363 | /* Send the compositor command to close the PDF14 device */ |
362 | code = gs_pop_pdf14trans_device(pgs, true); | 364 | code = gs_pop_pdf14trans_device(pgs, true); |
363 | if (code < 0) | 365 | if (code < 0) { |
366 | esp -= 5; | ||
364 | return code; | 367 | return code; |
368 | } | ||
365 | } else { | 369 | } else { |
366 | /* Not a clist, get PDF14 buffer information */ | 370 | /* Not a clist, get PDF14 buffer information */ |
367 | code = pdf14_get_buffer_information(pgs->device, | 371 | code = pdf14_get_buffer_information(pgs->device, |
@@ -369,8 +373,10 @@ pattern_paint_finish(i_ctx_t *i_ctx_p) | |||
369 | true); | 373 | true); |
370 | /* PDF14 device (and buffer) is destroyed when pattern cache | 374 | /* PDF14 device (and buffer) is destroyed when pattern cache |
371 | entry is removed */ | 375 | entry is removed */ |
372 | if (code < 0) | 376 | if (code < 0) { |
377 | esp -= 5; | ||
373 | return code; | 378 | return code; |
379 | } | ||
374 | } | 380 | } |
375 | } | 381 | } |
376 | code = gx_pattern_cache_add_entry(igs, pdev, &ctile); | 382 | code = gx_pattern_cache_add_entry(igs, pdev, &ctile); |