Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Unified Diff: frog/minfrog

Issue 9129023: adds array bounds checking (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: merged Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « frog/member.dart ('k') | tests/corelib/corelib.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: frog/minfrog
diff --git a/frog/minfrog b/frog/minfrog
index f80d87a1b7c2878b6bb74feaa6178e3fc7c3a96b..f33f065a2a3d2fbbe638ccf5bf41e84086a3e9d5 100755
--- a/frog/minfrog
+++ b/frog/minfrog
@@ -17,11 +17,17 @@ Object.defineProperty(Object.prototype, '$index', { value: function(i) {
}
return this[i];
}, enumerable: false, writable: true, configurable: true});
-Object.defineProperty(Array.prototype, '$index', { value: function(i) {
- return this[i];
+Object.defineProperty(Array.prototype, '$index', { value: function(index) {
+ var i = index | 0;
+ if (i !== index) {
+ throw new IllegalArgumentException('index is not int');
+ } else if (i < 0 || i >= this.length) {
+ throw new IndexOutOfRangeException(index);
+ }
+ return this[i];
}, enumerable: false, writable: true, configurable: true});
-Object.defineProperty(String.prototype, '$index', { value: function(i) {
- return this[i];
+Object.defineProperty(String.prototype, '$index', { value: function(i) {
+ return this[i];
}, enumerable: false, writable: true, configurable: true});
Object.defineProperty(Object.prototype, '$setindex', { value: function(i, value) {
var proto = Object.getPrototypeOf(this);
@@ -30,8 +36,14 @@ Object.defineProperty(Object.prototype, '$setindex', { value: function(i, value)
}
return this[i] = value;
}, enumerable: false, writable: true, configurable: true});
-Object.defineProperty(Array.prototype, '$setindex', { value: function(i, value) {
- return this[i] = value; }, enumerable: false, writable: true,
+Object.defineProperty(Array.prototype, '$setindex', { value: function(index, value) {
+ var i = index | 0;
+ if (i !== index) {
+ throw new IllegalArgumentException('index is not int');
+ } else if (i < 0 || i >= this.length) {
+ throw new IndexOutOfRangeException(index);
+ }
+ return this[i] = value; }, enumerable: false, writable: true,
configurable: true});
function $add(x, y) {
return ((typeof(x) == 'number' && typeof(y) == 'number') ||
@@ -50,7 +62,7 @@ function $eq(x, y) {
? x == y : x.$eq(y);
}
// TODO(jimhug): Should this or should it not match equals?
-Object.defineProperty(Object.prototype, '$eq', { value: function(other) {
+Object.defineProperty(Object.prototype, '$eq', { value: function(other) {
return this === other;
}, enumerable: false, writable: true, configurable: true });
function $gt(x, y) {
@@ -198,6 +210,15 @@ Clock.now = function() {
Clock.frequency = function() {
return (1000);
}
+// ********** Code for IndexOutOfRangeException **************
+function IndexOutOfRangeException(_index) {
+ this._index = _index;
+}
+IndexOutOfRangeException.prototype.is$IndexOutOfRangeException = function(){return true};
+IndexOutOfRangeException.prototype.toString = function() {
+ return ("IndexOutOfRangeException: " + this._index);
+}
+IndexOutOfRangeException.prototype.toString$0 = IndexOutOfRangeException.prototype.toString;
// ********** Code for IllegalAccessException **************
function IllegalAccessException() {
@@ -241,6 +262,15 @@ ObjectNotClosureException.prototype.toString = function() {
return "Object is not closure";
}
ObjectNotClosureException.prototype.toString$0 = ObjectNotClosureException.prototype.toString;
+// ********** Code for IllegalArgumentException **************
+function IllegalArgumentException(args) {
+ this._args = args;
+}
+IllegalArgumentException.prototype.is$IllegalArgumentException = function(){return true};
+IllegalArgumentException.prototype.toString = function() {
+ return ("Illegal argument(s): " + this._args);
+}
+IllegalArgumentException.prototype.toString$0 = IllegalArgumentException.prototype.toString;
// ********** Code for StackOverflowException **************
function StackOverflowException() {
@@ -281,6 +311,15 @@ EmptyQueueException.prototype.toString = function() {
return "EmptyQueueException";
}
EmptyQueueException.prototype.toString$0 = EmptyQueueException.prototype.toString;
+// ********** Code for IntegerDivisionByZeroException **************
+function IntegerDivisionByZeroException() {
+
+}
+IntegerDivisionByZeroException.prototype.is$IntegerDivisionByZeroException = function(){return true};
+IntegerDivisionByZeroException.prototype.toString = function() {
+ return "IntegerDivisionByZeroException";
+}
+IntegerDivisionByZeroException.prototype.toString$0 = IntegerDivisionByZeroException.prototype.toString;
// ********** Code for dart_core_Function **************
Function.prototype.to$call$0 = function() {
this.call$0 = this._genStub(0);
@@ -435,12 +474,22 @@ Object.defineProperty(ListFactory.prototype, "removeLast", { value: function() {
return this.pop();
}, enumerable: false, writable: true, configurable: true });
Object.defineProperty(ListFactory.prototype, "last", { value: function() {
- return this[this.get$length() - (1)];
+ return this.$index(this.get$length() - (1));
}, enumerable: false, writable: true, configurable: true });
Object.defineProperty(ListFactory.prototype, "getRange", { value: function(start, length) {
- return this.slice(start, start + length);
+ if (length == 0) return [];
+ if (length < 0) throw new IllegalArgumentException('length');
+ if (start < 0 || start + length > this.length)
+ throw new IndexOutOfRangeException(start);
+ return this.slice(start, start + length);
+
}, enumerable: false, writable: true, configurable: true });
Object.defineProperty(ListFactory.prototype, "insertRange", { value: function(start, length, initialValue) {
+ if (length == 0) return;
+ if (length < 0) throw new IllegalArgumentException('length');
+ if (start < 0 || start > this.length)
+ throw new IndexOutOfRangeException(start);
+
// Splice in the values with a minimum of array allocations.
var args = new Array(length + 2);
args[0] = start;
@@ -1613,7 +1662,7 @@ function $dynamic(name) {
var proto = Object.getPrototypeOf(obj);
if (!proto.hasOwnProperty(name)) {
Object.defineProperty(proto, name,
- { value: method, enumerable: false, writable: true,
+ { value: method, enumerable: false, writable: true,
configurable: true });
}
@@ -2749,7 +2798,6 @@ CodeWriter.prototype.nextBlock = function(text) {
CodeWriter.prototype.write$1 = CodeWriter.prototype.write;
// ********** Code for CoreJs **************
function CoreJs() {
- this.useAssert = false;
this.useIsolates = false;
this._generatedTypeNameOf = false;
this._usedOperators = new HashMapImplementation();
@@ -2776,7 +2824,7 @@ CoreJs.prototype.useOperator = function(name) {
case ":eq":
- code = "function $eq(x, y) {\n if (x == null) return y == null;\n return (typeof(x) == 'number' && typeof(y) == 'number') ||\n (typeof(x) == 'boolean' && typeof(y) == 'boolean') ||\n (typeof(x) == 'string' && typeof(y) == 'string')\n ? x == y : x.$eq(y);\n}\n// TODO(jimhug): Should this or should it not match equals?\nObject.defineProperty(Object.prototype, '$eq', { value: function(other) { \n return this === other;\n}, enumerable: false, writable: true, configurable: true });";
+ code = "function $eq(x, y) {\n if (x == null) return y == null;\n return (typeof(x) == 'number' && typeof(y) == 'number') ||\n (typeof(x) == 'boolean' && typeof(y) == 'boolean') ||\n (typeof(x) == 'string' && typeof(y) == 'string')\n ? x == y : x.$eq(y);\n}\n// TODO(jimhug): Should this or should it not match equals?\nObject.defineProperty(Object.prototype, '$eq', { value: function(other) {\n return this === other;\n}, enumerable: false, writable: true, configurable: true });";
break;
case ":bit_not":
@@ -2797,6 +2845,7 @@ CoreJs.prototype.useOperator = function(name) {
case ":truncdiv":
this.useThrow = true;
+ $globals.world.gen.markTypeUsed($globals.world.corelib.types.$index("IntegerDivisionByZeroException"));
code = "function $truncdiv(x, y) {\n if (typeof(x) == 'number' && typeof(y) == 'number') {\n if (y == 0) $throw(new IntegerDivisionByZeroException());\n var tmp = x / y;\n return (tmp < 0) ? Math.ceil(tmp) : Math.floor(tmp);\n } else {\n return x.$truncdiv(y);\n }\n}";
break;
@@ -2819,7 +2868,7 @@ CoreJs.prototype.ensureDynamicProto = function() {
if (this._generatedDynamicProto) return;
this._generatedDynamicProto = true;
this.ensureTypeNameOf();
- this.writer.writeln("function $dynamic(name) {\n var f = Object.prototype[name];\n if (f && f.methods) return f.methods;\n\n var methods = {};\n if (f) methods.Object = f;\n function $dynamicBind() {\n // Find the target method\n var obj = this;\n var tag = obj.$typeNameOf();\n var method = methods[tag];\n if (!method) {\n var table = $dynamicMetadata;\n for (var i = 0; i < table.length; i++) {\n var entry = table[i];\n if (entry.map.hasOwnProperty(tag)) {\n method = methods[entry.tag];\n if (method) break;\n }\n }\n }\n method = method || methods.Object;\n var proto = Object.getPrototypeOf(obj);\n if (!proto.hasOwnProperty(name)) {\n Object.defineProperty(proto, name,\n { value: method, enumerable: false, writable: true, \n configurable: true });\n }\n\n return method.apply(this, Array.prototype.slice.call(arguments));\n };\n $dynamicBind.methods = methods;\n Object.defineProperty(Object.prototype, name, { value: $dynamicBind,\n enumerable: false, writable: true, configurable: true});\n return methods;\n}\nif (typeof $dynamicMetadata == 'undefined') $dynamicMetadata = [];\n\nfunction $dynamicSetMetadata(inputTable) {\n // TODO: Deal with light isolates.\n var table = [];\n for (var i = 0; i < inputTable.length; i++) {\n var tag = inputTable[i][0];\n var tags = inputTable[i][1];\n var map = {};\n var tagNames = tags.split('|');\n for (var j = 0; j < tagNames.length; j++) {\n map[tagNames[j]] = true;\n }\n table.push({tag: tag, tags: tags, map: map});\n }\n $dynamicMetadata = table;\n}\n");
+ this.writer.writeln("function $dynamic(name) {\n var f = Object.prototype[name];\n if (f && f.methods) return f.methods;\n\n var methods = {};\n if (f) methods.Object = f;\n function $dynamicBind() {\n // Find the target method\n var obj = this;\n var tag = obj.$typeNameOf();\n var method = methods[tag];\n if (!method) {\n var table = $dynamicMetadata;\n for (var i = 0; i < table.length; i++) {\n var entry = table[i];\n if (entry.map.hasOwnProperty(tag)) {\n method = methods[entry.tag];\n if (method) break;\n }\n }\n }\n method = method || methods.Object;\n var proto = Object.getPrototypeOf(obj);\n if (!proto.hasOwnProperty(name)) {\n Object.defineProperty(proto, name,\n { value: method, enumerable: false, writable: true,\n configurable: true });\n }\n\n return method.apply(this, Array.prototype.slice.call(arguments));\n };\n $dynamicBind.methods = methods;\n Object.defineProperty(Object.prototype, name, { value: $dynamicBind,\n enumerable: false, writable: true, configurable: true});\n return methods;\n}\nif (typeof $dynamicMetadata == 'undefined') $dynamicMetadata = [];\n\nfunction $dynamicSetMetadata(inputTable) {\n // TODO: Deal with light isolates.\n var table = [];\n for (var i = 0; i < inputTable.length; i++) {\n var tag = inputTable[i][0];\n var tags = inputTable[i][1];\n var map = {};\n var tagNames = tags.split('|');\n for (var j = 0; j < tagNames.length; j++) {\n map[tagNames[j]] = true;\n }\n table.push({tag: tag, tags: tags, map: map});\n }\n $dynamicMetadata = table;\n}\n");
}
CoreJs.prototype.ensureTypeNameOf = function() {
if (this._generatedTypeNameOf) return;
@@ -2842,10 +2891,10 @@ CoreJs.prototype.generate = function(w) {
w.writeln("function $throw(e) {\n // If e is not a value, we can use V8's captureStackTrace utility method.\n // TODO(jmesserly): capture the stack trace on other JS engines.\n if (e && (typeof e == 'object') && Error.captureStackTrace) {\n // TODO(jmesserly): this will clobber the e.stack property\n Error.captureStackTrace(e, $throw);\n }\n throw e;\n}");
}
if (this.useIndex) {
- w.writeln("Object.defineProperty(Object.prototype, '$index', { value: function(i) {\n var proto = Object.getPrototypeOf(this);\n if (proto !== Object) {\n proto.$index = function(i) { return this[i]; }\n }\n return this[i];\n}, enumerable: false, writable: true, configurable: true});\nObject.defineProperty(Array.prototype, '$index', { value: function(i) { \n return this[i]; \n}, enumerable: false, writable: true, configurable: true});\nObject.defineProperty(String.prototype, '$index', { value: function(i) { \n return this[i]; \n}, enumerable: false, writable: true, configurable: true});");
+ w.writeln($globals.options.disableBoundsChecks ? "Object.defineProperty(Object.prototype, '$index', { value: function(i) {\n var proto = Object.getPrototypeOf(this);\n if (proto !== Object) {\n proto.$index = function(i) { return this[i]; }\n }\n return this[i];\n}, enumerable: false, writable: true, configurable: true});\nObject.defineProperty(Array.prototype, '$index', { value: function(i) {\n return this[i];\n}, enumerable: false, writable: true, configurable: true});\nObject.defineProperty(String.prototype, '$index', { value: function(i) {\n return this[i];\n}, enumerable: false, writable: true, configurable: true});" : "Object.defineProperty(Object.prototype, '$index', { value: function(i) {\n var proto = Object.getPrototypeOf(this);\n if (proto !== Object) {\n proto.$index = function(i) { return this[i]; }\n }\n return this[i];\n}, enumerable: false, writable: true, configurable: true});\nObject.defineProperty(Array.prototype, '$index', { value: function(index) {\n var i = index | 0;\n if (i !== index) {\n throw new IllegalArgumentException('index is not int');\n } else if (i < 0 || i >= this.length) {\n throw new IndexOutOfRangeException(index);\n }\n return this[i];\n}, enumerable: false, writable: true, configurable: true});\nObject.defineProperty(String.prototype, '$index', { value: function(i) {\n return this[i];\n}, enumerable: false, writable: true, configurable: true});");
}
if (this.useSetIndex) {
- w.writeln("Object.defineProperty(Object.prototype, '$setindex', { value: function(i, value) {\n var proto = Object.getPrototypeOf(this);\n if (proto !== Object) {\n proto.$setindex = function(i, value) { return this[i] = value; }\n }\n return this[i] = value;\n}, enumerable: false, writable: true, configurable: true});\nObject.defineProperty(Array.prototype, '$setindex', { value: function(i, value) { \n return this[i] = value; }, enumerable: false, writable: true, \n configurable: true});");
+ w.writeln($globals.options.disableBoundsChecks ? "Object.defineProperty(Object.prototype, '$setindex', { value: function(i, value) {\n var proto = Object.getPrototypeOf(this);\n if (proto !== Object) {\n proto.$setindex = function(i, value) { return this[i] = value; }\n }\n return this[i] = value;\n}, enumerable: false, writable: true, configurable: true});\nObject.defineProperty(Array.prototype, '$setindex', { value: function(i, value) {\n return this[i] = value; }, enumerable: false, writable: true,\n configurable: true});" : "Object.defineProperty(Object.prototype, '$setindex', { value: function(i, value) {\n var proto = Object.getPrototypeOf(this);\n if (proto !== Object) {\n proto.$setindex = function(i, value) { return this[i] = value; }\n }\n return this[i] = value;\n}, enumerable: false, writable: true, configurable: true});\nObject.defineProperty(Array.prototype, '$setindex', { value: function(index, value) {\n var i = index | 0;\n if (i !== index) {\n throw new IllegalArgumentException('index is not int');\n } else if (i < 0 || i >= this.length) {\n throw new IndexOutOfRangeException(index);\n }\n return this[i] = value; }, enumerable: false, writable: true,\n configurable: true});");
}
if (this.useIsolates) {
if (this.useWrap0) {
@@ -3053,6 +3102,12 @@ WorldGenerator.prototype.run = function() {
}
$globals.world.numImplType.markUsed();
$globals.world.stringImplType.markUsed();
+ if (this.corejs.useIndex || this.corejs.useSetIndex) {
+ if (!$globals.options.disableBoundsChecks) {
+ this.markTypeUsed($globals.world.corelib.types.$index("IndexOutOfRangeException"));
+ this.markTypeUsed($globals.world.corelib.types.$index("IllegalArgumentException"));
+ }
+ }
if ($globals.world.corelib.types.$index("Isolate").get$isUsed() || $globals.world.coreimpl.types.$index("ReceivePortImpl").get$isUsed()) {
if (this.corejs.useWrap0 || this.corejs.useWrap1) {
this.genMethod($globals.world.coreimpl.types.$index("IsolateContext").getMember("eval"));
@@ -6379,7 +6434,7 @@ MethodMember.prototype._invokeBuiltin = function(context, node, target, args, ar
return new Value(this.declaringType, ("" + target.get$code() + " + " + argsCode.$index((0))), node.span);
}
}
- else if (this.declaringType.get$isNative()) {
+ else if (this.declaringType.get$isNative() && $globals.options.disableBoundsChecks) {
if (args.get$length() > (0) && args.values.$index((0)).get$type().get$isNum()) {
if (this.name == ":index") {
return new Value(this.returnType, ("" + target.get$code() + "[" + argsCode.$index((0)) + "]"), node.span);
@@ -14056,22 +14111,23 @@ World.prototype.withTiming = function(name, f) {
// ********** Code for FrogOptions **************
function FrogOptions(homedir, args, files) {
this.legOnly = false;
- this.throwOnFatal = false;
+ this.disableBoundsChecks = false;
this.maxInferenceIterations = (4);
- this.config = "dev";
this.throwOnWarnings = false;
this.inferTypes = false;
- this.verifyImplements = false;
this.warningsAsErrors = false;
- this.enableLeg = false;
this.enableAsserts = false;
- this.enableTypeChecks = false;
this.forceDynamic = false;
- this.showInfo = false;
this.dietParse = false;
- this.useColors = true;
this.compileOnly = false;
this.showWarnings = true;
+ this.throwOnFatal = false;
+ this.config = "dev";
+ this.verifyImplements = false;
+ this.enableLeg = false;
+ this.enableTypeChecks = false;
+ this.showInfo = false;
+ this.useColors = true;
this.compileAll = false;
this.throwOnErrors = false;
if ($eq(this.config, "dev")) {
@@ -14179,6 +14235,17 @@ function FrogOptions(homedir, args, files) {
this.inferTypes = true;
break;
+ case "--checked":
+
+ this.enableTypeChecks = true;
+ this.enableAsserts = true;
+ break;
+
+ case "--unchecked":
+
+ this.disableBoundsChecks = true;
+ break;
+
default:
if (arg.endsWith(".dart")) {
« no previous file with comments | « frog/member.dart ('k') | tests/corelib/corelib.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698