Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
fix($parse): prevent invocation of Function's bind, call and apply
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rodyhaddad authored and IgorMinar committed Jun 30, 2014
1 parent db713a1 commit 77ada4c
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 0 deletions.
17 changes: 17 additions & 0 deletions docs/content/error/$parse/isecff.ngdoc
Original file line number Diff line number Diff line change
@@ -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:

```
<div>{{user.sendInfo.call({}, true)}}</div>
```
8 changes: 8 additions & 0 deletions src/ng/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,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);
}
}
}
Expand Down
50 changes: 50 additions & 0 deletions test/ng/parseSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,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() {
Expand Down

0 comments on commit 77ada4c

Please sign in to comment.