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

Commit 07fa87a

Browse files
rodyhaddadIgorMinar
authored andcommitted
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.
1 parent 0af70eb commit 07fa87a

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@ngdoc error
2+
@name $parse:isecff
3+
@fullName Referencing 'call', 'apply' and 'bind' Disallowed
4+
@description
5+
6+
Occurs when an expression attempts to invoke Function's 'call', 'apply' or 'bind'.
7+
8+
Angular bans the invocation of 'call', 'apply' and 'bind' from within expressions
9+
since access is a known way to modify the behaviour of existing functions.
10+
11+
To resolve this error, avoid using these methods in expressions.
12+
13+
Example expression that would result in this error:
14+
15+
```
16+
<div>{{user.sendInfo.call({}, true)}}</div>
17+
```

src/ng/parse.js

+8
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,20 @@ function ensureSafeObject(obj, fullExpression) {
6464
return obj;
6565
}
6666

67+
var CALL = Function.prototype.call;
68+
var APPLY = Function.prototype.apply;
69+
var BIND = Function.prototype.bind;
70+
6771
function ensureSafeFunction(obj, fullExpression) {
6872
if (obj) {
6973
if (obj.constructor === obj) {
7074
throw $parseMinErr('isecfn',
7175
'Referencing Function in Angular expressions is disallowed! Expression: {0}',
7276
fullExpression);
77+
} else if (obj === CALL || obj === APPLY || obj === BIND) {
78+
throw $parseMinErr('isecff',
79+
'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
80+
fullExpression);
7381
}
7482
}
7583
}

test/ng/parseSpec.js

+51-1
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,56 @@ describe('parser', function() {
698698
});
699699
});
700700

701+
describe('Function prototype functions', function () {
702+
it('should NOT allow invocation to Function.call', function() {
703+
scope.fn = Function.prototype.call;
704+
705+
expect(function() {
706+
scope.$eval('$eval.call()')
707+
}).toThrowMinErr(
708+
'$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' +
709+
'Expression: $eval.call()');
710+
711+
expect(function() {
712+
scope.$eval('fn()')
713+
}).toThrowMinErr(
714+
'$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' +
715+
'Expression: fn()');
716+
});
717+
718+
it('should NOT allow invocation to Function.apply', function() {
719+
scope.apply = Function.prototype.apply;
720+
721+
expect(function() {
722+
scope.$eval('$eval.apply()')
723+
}).toThrowMinErr(
724+
'$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' +
725+
'Expression: $eval.apply()');
726+
727+
expect(function() {
728+
scope.$eval('apply()')
729+
}).toThrowMinErr(
730+
'$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' +
731+
'Expression: apply()');
732+
});
733+
734+
it('should NOT allow invocation to Function.bind', function() {
735+
scope.bind = Function.prototype.bind;
736+
737+
expect(function() {
738+
scope.$eval('$eval.bind()')
739+
}).toThrowMinErr(
740+
'$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' +
741+
'Expression: $eval.bind()');
742+
743+
expect(function() {
744+
scope.$eval('bind()')
745+
}).toThrowMinErr(
746+
'$parse', 'isecff', 'Referencing call, apply or bind in Angular expressions is disallowed! ' +
747+
'Expression: bind()');
748+
});
749+
});
750+
701751
describe('Object constructor', function() {
702752

703753
it('should NOT allow access to Object constructor that has been aliased', function() {
@@ -1053,7 +1103,7 @@ describe('parser', function() {
10531103
}));
10541104
});
10551105

1056-
1106+
10571107
describe('constant', function() {
10581108
it('should mark scalar value expressions as constant', inject(function($parse) {
10591109
expect($parse('12.3').constant).toBe(true);

0 commit comments

Comments
 (0)