Discussion:
[gs-code-review] CET 20-02-02, don't restore the argument of operator begin
Alex Cherepanov
2007-04-05 21:29:22 UTC
Permalink
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();
Leonardo
2007-04-06 03:28:29 UTC
Permalink
Alex,

I think you should go ahead with committing it.
It looks satisfying old Peter's remark.
A better review may appear later.
Please insert space lines in 2 places after variable definition
as C-style.htm requires.

Igor.


----- Original Message -----
From: "Alex Cherepanov" <***@quadnet.net>
To: "gs-code-review" <gs-code-***@ghostscript.com>
Sent: Friday, April 06, 2007 3:36 AM
Subject: [gs-code-review] CET 20-02-02,don't restore the argument of
operator begin
Post by Alex Cherepanov
Following Adobe implementation don't restore the operand of --begin--
when it overflows the dictionary stack. Fix CET 20-02-02.
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.
No other CET or Comparefiles differences.
--------------------------------------------------------------------------------
Post by Alex Cherepanov
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) {
- 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();
--------------------------------------------------------------------------------
Post by Alex Cherepanov
_______________________________________________
gs-code-review mailing list
http://www.ghostscript.com/mailman/listinfo/gs-code-review
Loading...