From 07fa87a8a82b8be155d8c898bb79e5d9277adfb4 Mon Sep 17 00:00:00 2001 From: rodyhaddad Date: Thu, 26 Jun 2014 15:25:11 -0700 Subject: [PATCH] fix($parse): prevent invocation of Function's bind, call and apply BREAKING CHANGE: You can no longer invoke .bind, .call or .apply on a function in angular expressions. This is to disallow changing the behaviour of existing functions in an unforseen fashion. --- docs/content/error/$parse/isecff.ngdoc | 17 +++++++++ src/ng/parse.js | 8 ++++ test/ng/parseSpec.js | 52 +++++++++++++++++++++++++- 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 docs/content/error/$parse/isecff.ngdoc diff --git a/docs/content/error/$parse/isecff.ngdoc b/docs/content/error/$parse/isecff.ngdoc new file mode 100644 index 00000000..d06d259c --- /dev/null +++ b/docs/content/error/$parse/isecff.ngdoc @@ -0,0 +1,17 @@ +@ngdoc error +@name $parse:isecff +@fullName Referencing 'call', 'apply' and 'bind' Disallowed +@description + +Occurs when an expression attempts to invoke Function's 'call', 'apply' or 'bind'. + +Angular bans the invocation of 'call', 'apply' and 'bind' from within expressions +since access is a known way to modify the behaviour of existing functions. + +To resolve this error, avoid using these methods in expressions. + +Example expression that would result in this error: + +``` +
{{user.sendInfo.call({}, true)}}
+``` \ No newline at end of file diff --git a/src/ng/parse.js b/src/ng/parse.js index 933bda8e..fbee2f9f 100644 --- a/src/ng/parse.js +++ b/src/ng/parse.js @@ -64,12 +64,20 @@ function ensureSafeObject(obj, fullExpression) { return obj; } +var CALL = Function.prototype.call; +var APPLY = Function.prototype.apply; +var BIND = Function.prototype.bind; + function ensureSafeFunction(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { throw $parseMinErr('isecfn', 'Referencing Function in Angular expressions is disallowed! Expression: {0}', fullExpression); + } else if (obj === CALL || obj === APPLY || obj === BIND) { + throw $parseMinErr('isecff', + 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}', + fullExpression); } } } diff --git a/test/ng/parseSpec.js b/test/ng/parseSpec.js index b1f2ddd8..c45b6a9a 100644 --- a/test/ng/parseSpec.js +++ b/test/ng/parseSpec.js @@ -698,6 +698,56 @@ describe('parser', function() { }); }); + describe('Function prototype functions', function () { + it('should NOT allow invocation to Function.call', function() { + scope.fn = Function.prototype.call; + + expect(function() { + scope.$eval('$eval.call()') + }).toThrowMinErr( + '$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' + + 'Expression: $eval.call()'); + + expect(function() { + scope.$eval('fn()') + }).toThrowMinErr( + '$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' + + 'Expression: fn()'); + }); + + it('should NOT allow invocation to Function.apply', function() { + scope.apply = Function.prototype.apply; + + expect(function() { + scope.$eval('$eval.apply()') + }).toThrowMinErr( + '$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' + + 'Expression: $eval.apply()'); + + expect(function() { + scope.$eval('apply()') + }).toThrowMinErr( + '$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' + + 'Expression: apply()'); + }); + + it('should NOT allow invocation to Function.bind', function() { + scope.bind = Function.prototype.bind; + + expect(function() { + scope.$eval('$eval.bind()') + }).toThrowMinErr( + '$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' + + 'Expression: $eval.bind()'); + + expect(function() { + scope.$eval('bind()') + }).toThrowMinErr( + '$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' + + 'Expression: bind()'); + }); + }); + describe('Object constructor', function() { it('should NOT allow access to Object constructor that has been aliased', function() { @@ -1053,7 +1103,7 @@ describe('parser', function() { })); }); - + describe('constant', function() { it('should mark scalar value expressions as constant', inject(function($parse) { expect($parse('12.3').constant).toBe(true);