Fix for 687497, for loop with integer increment and big limit doesn't work

Alex Cherepanov <[email protected]> Sat, 05 Jun 2004 07:26:21 -0400
Newsgroups gmane.comp.printing.ghostscript.patches
Organization Coscript Software
Message-ID <[email protected]>
Check for integer overflow in the for loop control variable and
break out of the loop when the overflow is detected. Use
floating point calculations when the end value of the loop doesn't
fit into an integer. The latter change doesn't work well because of
the lower precision of float numbers and rounding effects.

The test file attached shows (among other things) the effects of
integer to float conversion.

_______________________________________________
gs-code-review mailing list
[email protected]
http://www.ghostscript.com/mailman/listinfo/gs-code-review
zcontrol.c.diff (text/plain, 2.4 KB)
Index: gs/src/zcontrol.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/zcontrol.c,v
retrieving revision 1.10
diff -b -u -r1.10 zcontrol.c
--- gs/src/zcontrol.c	16 Sep 2002 17:11:15 -0000	1.10
+++ gs/src/zcontrol.c	4 Jun 2004 23:30:25 -0000
@@ -300,10 +300,10 @@
     os_ptr op = osp;
     register es_ptr ep;
 
-    check_estack(7);
-    ep = esp + 6;
+    check_estack(8);
+    ep = esp + 7;
     check_proc(*op);
-    /* Push a mark, the control variable set to the initial value, */
+    /* Push a mark, the initial value, the control variable set to the initial value, */
     /* the increment, the limit, and the procedure, */
     /* and invoke the continuation operator. */
     if (r_has_type(op - 3, t_integer) &&
@@ -316,6 +316,10 @@
 		make_int(ep - 2, op[-1].value.intval);
 		break;
 	    case t_real:
+		if (op[-1].value.realval >= max_long + 1.0 ||
+                    op[-1].value.realval <= min_long - 1.0 )
+                    goto float_loop;
+                /* Not a bug! "-1 1 -0.5 {==} for" prints -1 0 on Adobe */
 		make_int(ep - 2, (long)op[-1].value.realval);
 		break;
 	    default:
@@ -326,6 +330,8 @@
 	else
 	    make_op_estack(ep, for_neg_int_continue);
     } else {
+        float_loop:;
+	{
 	float params[3];
 	int code;
 
@@ -336,7 +342,9 @@
 	make_real(ep - 2, params[2]);
 	make_op_estack(ep, for_real_continue);
     }
-    make_mark_estack(ep - 5, es_for, no_cleanup);
+    }
+    make_mark_estack(ep - 6, es_for, no_cleanup);
+    ref_assign(ep - 5, ep - 4);
     ref_assign(ep - 1, op);
     esp = ep;
     pop(4);
@@ -354,8 +362,9 @@
     register es_ptr ep = esp;
     long var = ep[-3].value.intval;
 
-    if (var > ep[-1].value.intval) {
-	esp -= 5;		/* pop everything */
+    if (var > ep[-1].value.intval ||
+        var < ep[-4].value.intval) {
+	esp -= 6;		/* pop everything */
 	return o_pop_estack;
     }
     push(1);
@@ -373,8 +382,9 @@
     register es_ptr ep = esp;
     long var = ep[-3].value.intval;
 
-    if (var < ep[-1].value.intval) {
-	esp -= 5;		/* pop everything */
+    if (var < ep[-1].value.intval ||
+        var > ep[-4].value.intval) {
+	esp -= 6;		/* pop everything */
 	return o_pop_estack;
     }
     push(1);
@@ -396,7 +406,7 @@
     if (incr >= 0 ? (var > ep[-1].value.realval) :
 	(var < ep[-1].value.realval)
 	) {
-	esp -= 5;		/* pop everything */
+	esp -= 6;		/* pop everything */
 	return o_pop_estack;
     }
     push(1);
for.ps (application/postscript, 2.4 KB) - not displayed