test($parse): test custom literals with CSP both enabled and disabled

(This commit also includes a minor clean-up.)
This commit is contained in:
Georgios Kalpakas
2016-07-21 23:28:35 +03:00
parent 10a6e1a663
commit d6423804a9
2 changed files with 36 additions and 30 deletions
+5 -4
View File
@@ -398,8 +398,7 @@ AST.prototype = {
filterChain: function() {
var left = this.expression();
var token;
while ((token = this.expect('|'))) {
while (this.expect('|')) {
left = this.filter(left);
}
return left;
@@ -695,6 +694,7 @@ function isStateless($filter, filterName) {
function findConstantAndWatchExpressions(ast, $filter) {
var allConstants;
var argsToWatch;
var isStatelessFilter;
switch (ast.type) {
case AST.Program:
allConstants = true;
@@ -745,7 +745,8 @@ function findConstantAndWatchExpressions(ast, $filter) {
ast.toWatch = [ast];
break;
case AST.CallExpression:
allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false;
isStatelessFilter = ast.filter ? isStateless($filter, ast.callee.name) : false;
allConstants = isStatelessFilter;
argsToWatch = [];
forEach(ast.arguments, function(expr) {
findConstantAndWatchExpressions(expr, $filter);
@@ -755,7 +756,7 @@ function findConstantAndWatchExpressions(ast, $filter) {
}
});
ast.constant = allConstants;
ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast];
ast.toWatch = isStatelessFilter ? argsToWatch : [ast];
break;
case AST.AssignmentExpression:
findConstantAndWatchExpressions(ast.left, $filter);
+31 -26
View File
@@ -868,7 +868,6 @@ describe('parser', function() {
});
it('should understand logical operators', function() {
forEach(['||', '&&'], function(operator) {
expect(createAst('foo' + operator + 'bar')).toEqual(
@@ -918,7 +917,6 @@ describe('parser', function() {
});
it('should understand ternary operators', function() {
expect(createAst('foo?bar:baz')).toEqual(
{
@@ -1083,7 +1081,6 @@ describe('parser', function() {
});
it('should give higher precedence to the logical `or` than to the conditional operator', function() {
expect(createAst('foo||bar?man:shell')).toEqual(
{
@@ -1355,6 +1352,7 @@ describe('parser', function() {
);
});
it('should understand ES6 object initializer', function() {
// Shorthand properties definitions.
expect(createAst('{x, y, z}')).toEqual(
@@ -1447,6 +1445,7 @@ describe('parser', function() {
);
});
it('should understand multiple expressions', function() {
expect(createAst('foo = bar; man = shell')).toEqual(
{
@@ -1551,6 +1550,7 @@ describe('parser', function() {
);
});
it('should give higher precedence to assignments over filters', function() {
expect(createAst('foo=bar | man')).toEqual(
{
@@ -1577,6 +1577,7 @@ describe('parser', function() {
);
});
it('should accept expression as filters parameters', function() {
expect(createAst('foo | bar:baz=man')).toEqual(
{
@@ -1604,6 +1605,7 @@ describe('parser', function() {
);
});
it('should accept expression as computer members', function() {
expect(createAst('foo[a = 1]')).toEqual(
{
@@ -1628,6 +1630,7 @@ describe('parser', function() {
);
});
it('should accept expression in function arguments', function() {
expect(createAst('foo(a = 1)')).toEqual(
{
@@ -1653,6 +1656,7 @@ describe('parser', function() {
);
});
it('should accept expression as part of ternary operators', function() {
expect(createAst('foo || bar ? man = 1 : shell = 1')).toEqual(
{
@@ -1687,6 +1691,7 @@ describe('parser', function() {
);
});
it('should accept expression as part of array literals', function() {
expect(createAst('[foo = 1]')).toEqual(
{
@@ -1711,6 +1716,7 @@ describe('parser', function() {
);
});
it('should accept expression as part of object literals', function() {
expect(createAst('{foo: bar = 1}')).toEqual(
{
@@ -1741,6 +1747,7 @@ describe('parser', function() {
);
});
it('should be possible to use parenthesis to indicate precedence', function() {
expect(createAst('(foo + bar).man')).toEqual(
{
@@ -1765,6 +1772,7 @@ describe('parser', function() {
);
});
it('should skip empty expressions', function() {
expect(createAst('foo;;;;bar')).toEqual(
{
@@ -1813,9 +1821,10 @@ describe('parser', function() {
}]));
forEach([true, false], function(cspEnabled) {
beforeEach(module(['$parseProvider', function(parseProvider) {
parseProvider.addLiteral('Infinity', Infinity);
}]));
beforeEach(module(function($parseProvider) {
$parseProvider.addLiteral('Infinity', Infinity);
csp().noUnsafeEval = cspEnabled;
}));
it('should allow extending literals with csp ' + cspEnabled, inject(function($rootScope) {
expect($rootScope.$eval("Infinity")).toEqual(Infinity);
@@ -2116,16 +2125,16 @@ describe('parser', function() {
expect(scope.b).toEqual(234);
});
it('should evaluate assignments in ternary operator', function() {
scope.$eval('a = 1 ? 2 : 3');
expect(scope.a).toBe(2);
it('should evaluate assignments in ternary operator', function() {
scope.$eval('a = 1 ? 2 : 3');
expect(scope.a).toBe(2);
scope.$eval('0 ? a = 2 : a = 3');
expect(scope.a).toBe(3);
scope.$eval('0 ? a = 2 : a = 3');
expect(scope.a).toBe(3);
scope.$eval('1 ? a = 2 : a = 3');
expect(scope.a).toBe(2);
});
scope.$eval('1 ? a = 2 : a = 3');
expect(scope.a).toBe(2);
});
it('should evaluate function call without arguments', function() {
scope['const'] = function(a, b) {return 123;};
@@ -2417,7 +2426,6 @@ describe('parser', function() {
}).toThrowMinErr(
'$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
'Expression: {}.toString.constructor');
});
it('should not allow access to the Function prototype in the getter', function() {
@@ -2426,7 +2434,6 @@ describe('parser', function() {
}).toThrowMinErr(
'$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
'Expression: toString.constructor.prototype');
});
it('should NOT allow access to Function constructor in getter', function() {
@@ -2435,7 +2442,6 @@ describe('parser', function() {
}).toThrowMinErr(
'$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
'Expression: {}.toString.constructor("alert(1)")');
});
it('should NOT allow access to Function constructor in setter', function() {
@@ -2936,14 +2942,14 @@ describe('parser', function() {
});
});
it('should prevent the exploit', function() {
expect(function() {
scope.$eval('(1)[{0: "__proto__", 1: "__proto__", 2: "__proto__", 3: "safe", length: 4, toString: [].pop}].foo = 1');
}).toThrow();
if (!msie || msie > 10) {
expect((1)['__proto__'].foo).toBeUndefined();
}
});
it('should prevent the exploit', function() {
expect(function() {
scope.$eval('(1)[{0: "__proto__", 1: "__proto__", 2: "__proto__", 3: "safe", length: 4, toString: [].pop}].foo = 1');
}).toThrow();
if (!msie || msie > 10) {
expect((1)['__proto__'].foo).toBeUndefined();
}
});
it('should prevent the exploit', function() {
expect(function() {
@@ -3337,7 +3343,6 @@ describe('parser', function() {
expect($rootScope.$$watchers.length).toBe(1);
expect(log).toEqual([]);
}));
});
});