Ver código fonte

fix integer arithmetics overflow (Issue #19).

Vladislav Folts 11 anos atrás
pai
commit
7aca683c3b

+ 8 - 7
src/context.js

@@ -697,9 +697,10 @@ function assertOpType(type, check, literal){
             type.description() + "'");
 }
 
-function assertNumericOp(type, literal, op){
+function assertNumericOp(type, literal, op, intOp){
     assertOpType(type, numericOpTypeCheck, literal);
-    return op;
+    return (intOp && type == basicTypes.integer)
+           ? intOp : op;
 }
 
 function assertIntOp(type, literal, op){
@@ -772,10 +773,10 @@ exports.AddOperator = ChainedContext.extend({
         var o;
         if (s == "+")
             o = (type == basicTypes.set) ? op.setUnion
-                                         : assertNumericOp(type, s, op.add);
+                                         : assertNumericOp(type, s, op.add, op.addInt);
         else if (s == "-")
             o = (type == basicTypes.set) ? op.setDiff
-                                         : assertNumericOp(type, s, op.sub);
+                                         : assertNumericOp(type, s, op.sub, op.subInt);
         else if (s == "OR"){
             if (type != basicTypes.bool)
                 throw new Errors.Error("BOOLEAN expected as operand of 'OR', got '"
@@ -797,17 +798,17 @@ exports.MulOperator = ChainedContext.extend({
         var o;
         if (s == "*")
             o = (type == basicTypes.set) ? op.setIntersection
-                                         : assertNumericOp(type, s, op.mul);
+                                         : assertNumericOp(type, s, op.mul, op.mulInt);
         else if (s == "/"){
             if (type == basicTypes.set)
                 o = op.setSymmetricDiff;
             else if (type == basicTypes.integer)
                 throw new Errors.Error("operator DIV expected for integer division");
             else
-                o = assertNumericOp(type, s, op.divFloat);
+                o = assertNumericOp(type, s, op.div);
         }
         else if (s == "DIV")
-            o = assertIntOp(type, s, op.div);
+            o = assertIntOp(type, s, op.divInt);
         else if (s == "MOD")
             o = assertIntOp(type, s, op.mod);
         else if (s == "&"){

+ 18 - 11
src/operator.js

@@ -51,7 +51,7 @@ function makeUnary(op, code){
 }
 
 var mul = makeBinary(function(x, y){return x * y;}, " * ", precedence.mulDivMod);
-var divFloat = makeBinary(function(x, y){return x / y;}, " / ", precedence.mulDivMod);
+var div = makeBinary(function(x, y){return x / y;}, " / ", precedence.mulDivMod);
 
 function pow2(e){
     return new Code.Expression("Math.pow(2, " + e.deref().code() + ")",
@@ -127,16 +127,23 @@ function makeInplace(code, altOp){
     };
 }
 
+function makeBinaryInt(op, code, prec){
+    return makeBinary(
+            function(x, y){return op(x, y) | 0;},
+            function(x, y){return x + code + y + " | 0";},
+            prec,
+            precedence.bitOr);
+}
+
 var operators = {
-    add: makeBinary(function(x, y){return x + y;}, " + ", precedence.addSub),
-    sub: makeBinary(function(x, y){return x - y;}, " - ", precedence.addSub),
-    mul: mul,
-    div: makeBinary(
-            function(x, y){return (x / y) | 0;},
-            function(x, y){return x + " / " + y + " | 0";},
-            precedence.mulDivMod,
-            precedence.bitOr),
-    divFloat:   divFloat,
+    add:    makeBinary(   function(x, y){return x + y;}, " + ", precedence.addSub),
+    addInt: makeBinaryInt(function(x, y){return x + y;}, " + ", precedence.addSub),
+    sub:    makeBinary(   function(x, y){return x - y;}, " - ", precedence.addSub),
+    subInt: makeBinaryInt(function(x, y){return x - y;}, " - ", precedence.addSub),
+    mul:    mul,
+    mulInt: makeBinaryInt(function(x, y){return x * y;}, " * ", precedence.mulDivMod),
+    div:    div,
+    divInt: makeBinaryInt(function(x, y){return x / y;}, " / ", precedence.mulDivMod),
     mod:        makeBinary(function(x, y){return x % y;}, " % ", precedence.mulDivMod),
     setUnion:   makeBinary(function(x, y){return x | y;}, " | ", precedence.bitOr),
     setDiff:    makeBinary(function(x, y){return x & ~y;}, " & ~", precedence.bitAnd),
@@ -170,7 +177,7 @@ var operators = {
 
     assign:     assign,
     mulInplace: makeInplace(" *= ", mul),
-    divInplace: makeInplace(" /= ", divFloat),
+    divInplace: makeInplace(" /= ", div),
     
     pow2:       pow2,
     log2:       log2

+ 7 - 4
test/expected/arithmetic.js

@@ -1,17 +1,20 @@
 var m = function (){
+var c1 = 2147483647 + 1 | 0;
+var c2 = 4294967295 * 2 | 0;
 var i1 = 0;var i2 = 0;
 var r1 = 0;var r2 = 0;
 i1 = 1;
 i2 = 2;
-i1 = i1 + i2;
-i1 = i1 - i2;
-i1 = i1 * i2;
+i1 = i1 + i2 | 0;
+i1 = i1 - i2 | 0;
+i1 = i1 * i2 | 0;
 i1 = i1 / i2 | 0;
 i1 = i1 % i2;
+i1 = 1 + (i1 * i2 | 0) | 0;
 r1 = 1;
 r2 = 2;
 r1 = r1 + r2;
 r1 = r1 - r2;
 r1 = r1 * r2;
 r1 = r1 / r2;
-}();
+}();

+ 9 - 9
test/expected/blur.js

@@ -20,9 +20,9 @@ var RTL$ = {
 };
 var Blur = function (){
 var W = 640;
-var W1 = 640 - 3;
+var W1 = 640 - 3 | 0;
 var H = 480;
-var H1 = 480 - 3;
+var H1 = 480 - 3 | 0;
 var N = 13;
 var Frames = 1;
 var a = RTL$.makeArray(1920, 480, 0);var b = RTL$.makeArray(1920, 480, 0);
@@ -34,17 +34,17 @@ function Blur2DArray(){
 	var color = 0;
 	for (f = 1; f <= Frames; ++f){
 		for (n = 1; n <= N; ++n){
-			for (y = 1; y <= H - 2; ++y){
-				for (x = 1; x <= W - 2; ++x){
+			for (y = 1; y <= H - 2 | 0; ++y){
+				for (x = 1; x <= W - 2 | 0; ++x){
 					for (color = 0; color <= 2; ++color){
-						b[x * 3 + color][y] = (a[x * 3 + color][y + 1] + a[x * 3 + color][y - 1] + a[(x - 1) * 3][y] + a[(x + 1) * 3][y]) / 4 | 0;
+						b[(x * 3 | 0) + color | 0][y] = (((a[(x * 3 | 0) + color | 0][y + 1 | 0] + a[(x * 3 | 0) + color | 0][y - 1 | 0] | 0) + a[(x - 1 | 0) * 3 | 0][y] | 0) + a[(x + 1 | 0) * 3 | 0][y] | 0) / 4 | 0;
 					}
 				}
 			}
-			for (y = 1; y <= H - 2; ++y){
-				for (x = 1; x <= W - 2; ++x){
+			for (y = 1; y <= H - 2 | 0; ++y){
+				for (x = 1; x <= W - 2 | 0; ++x){
 					for (color = 0; color <= 2; ++color){
-						a[x * 3 + color][y] = (b[x * 3 + color][y + 1] + b[x * 3 + color][y - 1] + b[(x - 1) * 3][y] + b[(x + 1) * 3][y]) / 4 | 0;
+						a[(x * 3 | 0) + color | 0][y] = (((b[(x * 3 | 0) + color | 0][y + 1 | 0] + b[(x * 3 | 0) + color | 0][y - 1 | 0] | 0) + b[(x - 1 | 0) * 3 | 0][y] | 0) + b[(x + 1 | 0) * 3 | 0][y] | 0) / 4 | 0;
 					}
 				}
 			}
@@ -55,4 +55,4 @@ Blur2DArray();
 return {
 	Blur2DArray: Blur2DArray
 }
-}();
+}();

+ 2 - 2
test/expected/const.js

@@ -1,7 +1,7 @@
 var m = function (){
 var i1 = 1;
 var b1 = true;
-var i2 = i1 + 2;
+var i2 = i1 + 2 | 0;
 var i3 = 31;
 var i4 = 10;
 var i5 = 3;
@@ -14,4 +14,4 @@ var lr1 = 23456700000000;
 var lr2 = 23.4567;
 var lr3 = 0.0000234567;
 var b2 = b1;
-}();
+}();

+ 2 - 2
test/expected/flt.js

@@ -1,5 +1,5 @@
 var m = function (){
 var r = 0;
 r = 123;
-r = 1.23 * (1 + 2);
-}();
+r = 1.23 * (1 + 2 | 0);
+}();

+ 2 - 2
test/expected/for.js

@@ -3,7 +3,7 @@ var i = 0;
 var b1 = false;
 var i1 = 0;
 for (i = 0; i <= 10; ++i){
-	i1 = i1 + 1;
+	i1 = i1 + 1 | 0;
 }
 for (i = 0; i <= 10; i += 5){
 	b1 = true;
@@ -14,4 +14,4 @@ for (i = 15; i >= 0; i -= 3){
 	}
 	i1 = -2;
 }
-}();
+}();

+ 5 - 3
test/expected/inc_dec.js

@@ -3,10 +3,12 @@ var ic = 10;
 var i = 0;
 ++i;
 i += 2;
-i += 15/*3 * 5*/;
+i += 15/*3 * 5 | 0*/;
 i += 10/*ic*/;
+i += -2147483648/*2147483647 + 1 | 0*/;
 --i;
 i -= 2;
-i -= 15/*3 * 5*/;
+i -= 15/*3 * 5 | 0*/;
 i -= 10/*ic*/;
-}();
+i -= -2/*4294967295 * 2 | 0*/;
+}();

+ 1 - 1
test/expected/man_or_boy.js

@@ -66,7 +66,7 @@ function Fn1(s/*PState*/){
 function A(s/*PState*/){
 	var res = 0;
 	if (s.k <= 0){
-		res = call(s.x4) + call(s.x5);
+		res = call(s.x4) + call(s.x5) | 0;
 	}
 	else {
 		res = call(makeState(pB, s.k, s.x1, s.x2, s.x3, s.x4, s.x5));

+ 2 - 2
test/expected/odd.js

@@ -9,7 +9,7 @@ var m = function (){
 var i = 0;
 RTL$.assert(1 & 1);
 i = 4;
-RTL$.assert(1 + i & 1);
+RTL$.assert((1 + i | 0) & 1);
 RTL$.assert(!(2 & 1));
 RTL$.assert((true || false ? 1 : 0) & 1);
-}();
+}();

+ 15 - 15
test/expected/parentheses.js

@@ -32,19 +32,19 @@ var s = 0;
 var a = RTL$.makeArray(10, 0);
 i = 65;
 ch = i;
-i = (ch + i) / 2 | 0;
+i = (ch + i | 0) / 2 | 0;
 RTL$.assert(i == 65);
-a[(i - 64) * 3] = i;
-i = i + (i - 1);
-i = i - i + 1;
-i = i * i + 1;
-i = i * (i + 1);
-i = (i / 2 | 0) + 1;
-i = i / (2 + 1) | 0;
+a[(i - 64 | 0) * 3 | 0] = i;
+i = i + (i - 1 | 0) | 0;
+i = (i - i | 0) + 1 | 0;
+i = (i * i | 0) + 1 | 0;
+i = i * (i + 1 | 0) | 0;
+i = (i / 2 | 0) + 1 | 0;
+i = i / (2 + 1 | 0) | 0;
 r = r / 2 + 1;
 r = r / (2 + 1);
-i = i % 2 + 1;
-i = i % (2 + 1);
+i = i % 2 + 1 | 0;
+i = i % (2 + 1 | 0);
 b = b && b || b;
 b = b && (b || b);
 b = b && b || b;
@@ -59,9 +59,9 @@ s = s & s ^ s;
 s = s & (s ^ s);
 s = s & s | s;
 s = s & (s | s);
-i = -(i * 2) + i;
-i = -(i * (2 + i));
-i = -(i % (2 * i));
-i = -i + 2 * i;
+i = -(i * 2 | 0) + i | 0;
+i = -(i * (2 + i | 0) | 0);
+i = -(i % (2 * i | 0));
+i = -i + (2 * i | 0) | 0;
 s = ~s & ~~s;
-}();
+}();

+ 2 - 2
test/expected/proc.js

@@ -32,7 +32,7 @@ function p1(arg1/*INTEGER*/){
 	var b = false;
 	var t1 = new T1();
 	var t2 = new T2();
-	i = arg1 + 1;
+	i = arg1 + 1 | 0;
 	t1.field1 = i;
 	t2.field1 = t1.field1;
 	b = true;
@@ -51,7 +51,7 @@ function p3(i/*INTEGER*/){
 }
 
 function p4(){
-	return p3(123) + p3(p3(123));
+	return p3(123) + p3(p3(123)) | 0;
 }
 
 function p5(){

+ 3 - 3
test/expected/set.js

@@ -74,7 +74,7 @@ s1 = 61;
 s1 = 8;
 s1 = 64;
 i1 = 3;
-s2 = RTL$.makeSet(i1, i1 + 2, [10 - i1, 15]);
+s2 = RTL$.makeSet(i1, i1 + 2 | 0, [10 - i1 | 0, 15]);
 s2 = RTL$.makeSet(i1) | 4;
 b = 1 << i1 & s1;
 b = RTL$.setInclL(s1, s2);
@@ -95,10 +95,10 @@ s1 = s1 & s2;
 s1 = s1 ^ s2;
 s1 = ~s2;
 s2 |= 8/*bit: 3*/;
-s1 |= 512/*bit: ci * 2 + 3*/;
+s1 |= 512/*bit: ((ci * 2 | 0) + 3 | 0)*/;
 s1 |= 2/*bit: (cb ? 1 : 0)*/;
 aSet[0] |= 8/*bit: 3*/;
 s2 &= ~(8/*bit: 3*/);
 s2 &= ~(1/*bit: (!cb ? 1 : 0)*/);
 aSet[0] &= ~(8/*bit: 3*/);
-}();
+}();

+ 2 - 2
test/expected/var_parameter.js

@@ -68,8 +68,8 @@ function p3(i/*VAR INTEGER*/, b/*VAR BOOLEAN*/){
 	var r = new R();
 	var ar = RTL$.makeArray(5, function(){return new R();});
 	var ai = RTL$.makeArray(5, 0);
-	j = i.get() + 1;
-	j = 2 * i.get();
+	j = i.get() + 1 | 0;
+	j = 2 * i.get() | 0;
 	j = i.get() / 2 | 0;
 	j = -i.get();
 	b.set(!b.get());

+ 4 - 0
test/input/arithmetic.ob

@@ -1,5 +1,8 @@
 MODULE m;
 
+CONST 
+	c1 = 07FFFFFFFH + 1; (* -2147483648 *)
+	c2 = 0FFFFFFFFH * 2; (* -2 *)
 VAR 
 	i1, i2: INTEGER;
 	r1, r2: REAL;
@@ -12,6 +15,7 @@ BEGIN
 	i1 := i1 * i2;
 	i1 := i1 DIV i2;
 	i1 := i1 MOD i2;
+	i1 := 1 + i1 * i2;
 
 	r1 := 1.0;
 	r2 := 2.0;

+ 2 - 0
test/input/inc_dec.ob

@@ -8,9 +8,11 @@ BEGIN
 	INC(i, 2);
 	INC(i, 3 * 5);
 	INC(i, ic);
+	INC(i, 07FFFFFFFH + 1 );
 
 	DEC(i);
 	DEC(i, 2);
 	DEC(i, 3 * 5);
 	DEC(i, ic);
+	DEC(i, 0FFFFFFFFH * 2);
 END m.