Alex Cherepanov
2007-04-05 21:29:22 UTC
Following Adobe implementation don't restore the operand of --begin--
when it overflows the dictionary stack. Fix CET 20-02-02.
DETAILS:
Implement the approach suggested by L. Peter Deutsch.
- Change the check_dstack macro in dstack.h so it works the same as
check_estack in estack.h -- i.e., if the current dstack block is full,
call ref_stack_extend and then only return an error if
ref_stack_extend fails.
- Change the handling of e_dictstackoverflow in interp.c so it works
the same as e_execstackoverflow -- i.e., it doesn't try to extend the
stack.
- Change the implementation of zbegin in zdict.c to work like
check_dstack. I.e., if the current dstack block is full, call
ref_stack_extend; if ref_stack_extend returns e_dictstackoverflow, pop
the operand from the ostack before returning the error code.
With this approach, the interpreter does not have to know anything about
special handling of dictstackoverflow, and the right thing happens in
the special case of the 'begin' operator.
DIFFERENCES:
No other CET or Comparefiles differences.
-------------- next part --------------
Index: gs/src/dstack.h
===================================================================
--- gs/src/dstack.h (revision 7816)
+++ gs/src/dstack.h (working copy)
@@ -46,7 +46,9 @@
/* Macro to ensure enough room on the dictionary stack */
#define check_dstack(n)\
if ( dstop - dsp < (n) )\
- { d_stack.requested = (n); return_error(e_dictstackoverflow); }
+ { int ds_code_ = ref_stack_extend(&d_stack, n);\
+ if ( ds_code_ < 0 ) return ds_code_;\
+ }
/*
* The dictionary stack is implemented as a linked list of blocks;
Index: gs/src/interp.c
===================================================================
--- gs/src/interp.c (revision 7816)
+++ gs/src/interp.c (working copy)
@@ -539,12 +539,10 @@
/* we might be able to recover by adding or removing a block. */
switch (code) {
case e_dictstackoverflow:
- if (ref_stack_extend(&d_stack, d_stack.requested) >= 0) {
- dict_set_top();
- doref = *perror_object;
- epref = &doref;
- goto again;
- }
+ /* We don't have to handle this specially: */
+ /* The only places that could generate it */
+ /* use check_dstack, which does a ref_stack_extend, */
+ /* so if` we get this error, it's a real one. */
if (osp >= ostop) {
if ((ccode = ref_stack_extend(&o_stack, 1)) < 0)
return ccode;
Index: gs/src/zdict.c
===================================================================
--- gs/src/zdict.c (revision 7816)
+++ gs/src/zdict.c (working copy)
@@ -59,8 +59,17 @@
check_type(*op, t_dictionary);
check_dict_read(*op);
- if (dsp == dstop)
- return_error(e_dictstackoverflow);
+ if ( dsp == dstop ) {
+ int code = ref_stack_extend(&d_stack, 1);
+ if ( code < 0 ) {
+ if (code == e_dictstackoverflow) {
+ /* Adobe doesn't restore the operand that caused stack */
+ /* overflow. We do the same to match CET 20-02-02 */
+ pop(1);
+ }
+ return code;
+ }
+ }
++dsp;
ref_assign(dsp, op);
dict_set_top();
when it overflows the dictionary stack. Fix CET 20-02-02.
DETAILS:
Implement the approach suggested by L. Peter Deutsch.
- Change the check_dstack macro in dstack.h so it works the same as
check_estack in estack.h -- i.e., if the current dstack block is full,
call ref_stack_extend and then only return an error if
ref_stack_extend fails.
- Change the handling of e_dictstackoverflow in interp.c so it works
the same as e_execstackoverflow -- i.e., it doesn't try to extend the
stack.
- Change the implementation of zbegin in zdict.c to work like
check_dstack. I.e., if the current dstack block is full, call
ref_stack_extend; if ref_stack_extend returns e_dictstackoverflow, pop
the operand from the ostack before returning the error code.
With this approach, the interpreter does not have to know anything about
special handling of dictstackoverflow, and the right thing happens in
the special case of the 'begin' operator.
DIFFERENCES:
No other CET or Comparefiles differences.
-------------- next part --------------
Index: gs/src/dstack.h
===================================================================
--- gs/src/dstack.h (revision 7816)
+++ gs/src/dstack.h (working copy)
@@ -46,7 +46,9 @@
/* Macro to ensure enough room on the dictionary stack */
#define check_dstack(n)\
if ( dstop - dsp < (n) )\
- { d_stack.requested = (n); return_error(e_dictstackoverflow); }
+ { int ds_code_ = ref_stack_extend(&d_stack, n);\
+ if ( ds_code_ < 0 ) return ds_code_;\
+ }
/*
* The dictionary stack is implemented as a linked list of blocks;
Index: gs/src/interp.c
===================================================================
--- gs/src/interp.c (revision 7816)
+++ gs/src/interp.c (working copy)
@@ -539,12 +539,10 @@
/* we might be able to recover by adding or removing a block. */
switch (code) {
case e_dictstackoverflow:
- if (ref_stack_extend(&d_stack, d_stack.requested) >= 0) {
- dict_set_top();
- doref = *perror_object;
- epref = &doref;
- goto again;
- }
+ /* We don't have to handle this specially: */
+ /* The only places that could generate it */
+ /* use check_dstack, which does a ref_stack_extend, */
+ /* so if` we get this error, it's a real one. */
if (osp >= ostop) {
if ((ccode = ref_stack_extend(&o_stack, 1)) < 0)
return ccode;
Index: gs/src/zdict.c
===================================================================
--- gs/src/zdict.c (revision 7816)
+++ gs/src/zdict.c (working copy)
@@ -59,8 +59,17 @@
check_type(*op, t_dictionary);
check_dict_read(*op);
- if (dsp == dstop)
- return_error(e_dictstackoverflow);
+ if ( dsp == dstop ) {
+ int code = ref_stack_extend(&d_stack, 1);
+ if ( code < 0 ) {
+ if (code == e_dictstackoverflow) {
+ /* Adobe doesn't restore the operand that caused stack */
+ /* overflow. We do the same to match CET 20-02-02 */
+ pop(1);
+ }
+ return code;
+ }
+ }
++dsp;
ref_assign(dsp, op);
dict_set_top();