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

Commit d642380

Browse files
committed
test($parse): test custom literals with CSP both enabled and disabled
(This commit also includes a minor clean-up.)
1 parent 10a6e1a commit d642380

File tree

2 files changed

+36
-30
lines changed

2 files changed

+36
-30
lines changed

src/ng/parse.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,7 @@ AST.prototype = {
398398

399399
filterChain: function() {
400400
var left = this.expression();
401-
var token;
402-
while ((token = this.expect('|'))) {
401+
while (this.expect('|')) {
403402
left = this.filter(left);
404403
}
405404
return left;
@@ -695,6 +694,7 @@ function isStateless($filter, filterName) {
695694
function findConstantAndWatchExpressions(ast, $filter) {
696695
var allConstants;
697696
var argsToWatch;
697+
var isStatelessFilter;
698698
switch (ast.type) {
699699
case AST.Program:
700700
allConstants = true;
@@ -745,7 +745,8 @@ function findConstantAndWatchExpressions(ast, $filter) {
745745
ast.toWatch = [ast];
746746
break;
747747
case AST.CallExpression:
748-
allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false;
748+
isStatelessFilter = ast.filter ? isStateless($filter, ast.callee.name) : false;
749+
allConstants = isStatelessFilter;
749750
argsToWatch = [];
750751
forEach(ast.arguments, function(expr) {
751752
findConstantAndWatchExpressions(expr, $filter);
@@ -755,7 +756,7 @@ function findConstantAndWatchExpressions(ast, $filter) {
755756
}
756757
});
757758
ast.constant = allConstants;
758-
ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast];
759+
ast.toWatch = isStatelessFilter ? argsToWatch : [ast];
759760
break;
760761
case AST.AssignmentExpression:
761762
findConstantAndWatchExpressions(ast.left, $filter);

test/ng/parseSpec.js

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,6 @@ describe('parser', function() {
868868
});
869869

870870

871-
872871
it('should understand logical operators', function() {
873872
forEach(['||', '&&'], function(operator) {
874873
expect(createAst('foo' + operator + 'bar')).toEqual(
@@ -918,7 +917,6 @@ describe('parser', function() {
918917
});
919918

920919

921-
922920
it('should understand ternary operators', function() {
923921
expect(createAst('foo?bar:baz')).toEqual(
924922
{
@@ -1083,7 +1081,6 @@ describe('parser', function() {
10831081
});
10841082

10851083

1086-
10871084
it('should give higher precedence to the logical `or` than to the conditional operator', function() {
10881085
expect(createAst('foo||bar?man:shell')).toEqual(
10891086
{
@@ -1355,6 +1352,7 @@ describe('parser', function() {
13551352
);
13561353
});
13571354

1355+
13581356
it('should understand ES6 object initializer', function() {
13591357
// Shorthand properties definitions.
13601358
expect(createAst('{x, y, z}')).toEqual(
@@ -1447,6 +1445,7 @@ describe('parser', function() {
14471445
);
14481446
});
14491447

1448+
14501449
it('should understand multiple expressions', function() {
14511450
expect(createAst('foo = bar; man = shell')).toEqual(
14521451
{
@@ -1551,6 +1550,7 @@ describe('parser', function() {
15511550
);
15521551
});
15531552

1553+
15541554
it('should give higher precedence to assignments over filters', function() {
15551555
expect(createAst('foo=bar | man')).toEqual(
15561556
{
@@ -1577,6 +1577,7 @@ describe('parser', function() {
15771577
);
15781578
});
15791579

1580+
15801581
it('should accept expression as filters parameters', function() {
15811582
expect(createAst('foo | bar:baz=man')).toEqual(
15821583
{
@@ -1604,6 +1605,7 @@ describe('parser', function() {
16041605
);
16051606
});
16061607

1608+
16071609
it('should accept expression as computer members', function() {
16081610
expect(createAst('foo[a = 1]')).toEqual(
16091611
{
@@ -1628,6 +1630,7 @@ describe('parser', function() {
16281630
);
16291631
});
16301632

1633+
16311634
it('should accept expression in function arguments', function() {
16321635
expect(createAst('foo(a = 1)')).toEqual(
16331636
{
@@ -1653,6 +1656,7 @@ describe('parser', function() {
16531656
);
16541657
});
16551658

1659+
16561660
it('should accept expression as part of ternary operators', function() {
16571661
expect(createAst('foo || bar ? man = 1 : shell = 1')).toEqual(
16581662
{
@@ -1687,6 +1691,7 @@ describe('parser', function() {
16871691
);
16881692
});
16891693

1694+
16901695
it('should accept expression as part of array literals', function() {
16911696
expect(createAst('[foo = 1]')).toEqual(
16921697
{
@@ -1711,6 +1716,7 @@ describe('parser', function() {
17111716
);
17121717
});
17131718

1719+
17141720
it('should accept expression as part of object literals', function() {
17151721
expect(createAst('{foo: bar = 1}')).toEqual(
17161722
{
@@ -1741,6 +1747,7 @@ describe('parser', function() {
17411747
);
17421748
});
17431749

1750+
17441751
it('should be possible to use parenthesis to indicate precedence', function() {
17451752
expect(createAst('(foo + bar).man')).toEqual(
17461753
{
@@ -1765,6 +1772,7 @@ describe('parser', function() {
17651772
);
17661773
});
17671774

1775+
17681776
it('should skip empty expressions', function() {
17691777
expect(createAst('foo;;;;bar')).toEqual(
17701778
{
@@ -1813,9 +1821,10 @@ describe('parser', function() {
18131821
}]));
18141822

18151823
forEach([true, false], function(cspEnabled) {
1816-
beforeEach(module(['$parseProvider', function(parseProvider) {
1817-
parseProvider.addLiteral('Infinity', Infinity);
1818-
}]));
1824+
beforeEach(module(function($parseProvider) {
1825+
$parseProvider.addLiteral('Infinity', Infinity);
1826+
csp().noUnsafeEval = cspEnabled;
1827+
}));
18191828

18201829
it('should allow extending literals with csp ' + cspEnabled, inject(function($rootScope) {
18211830
expect($rootScope.$eval("Infinity")).toEqual(Infinity);
@@ -2116,16 +2125,16 @@ describe('parser', function() {
21162125
expect(scope.b).toEqual(234);
21172126
});
21182127

2119-
it('should evaluate assignments in ternary operator', function() {
2120-
scope.$eval('a = 1 ? 2 : 3');
2121-
expect(scope.a).toBe(2);
2128+
it('should evaluate assignments in ternary operator', function() {
2129+
scope.$eval('a = 1 ? 2 : 3');
2130+
expect(scope.a).toBe(2);
21222131

2123-
scope.$eval('0 ? a = 2 : a = 3');
2124-
expect(scope.a).toBe(3);
2132+
scope.$eval('0 ? a = 2 : a = 3');
2133+
expect(scope.a).toBe(3);
21252134

2126-
scope.$eval('1 ? a = 2 : a = 3');
2127-
expect(scope.a).toBe(2);
2128-
});
2135+
scope.$eval('1 ? a = 2 : a = 3');
2136+
expect(scope.a).toBe(2);
2137+
});
21292138

21302139
it('should evaluate function call without arguments', function() {
21312140
scope['const'] = function(a, b) {return 123;};
@@ -2417,7 +2426,6 @@ describe('parser', function() {
24172426
}).toThrowMinErr(
24182427
'$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
24192428
'Expression: {}.toString.constructor');
2420-
24212429
});
24222430

24232431
it('should not allow access to the Function prototype in the getter', function() {
@@ -2426,7 +2434,6 @@ describe('parser', function() {
24262434
}).toThrowMinErr(
24272435
'$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
24282436
'Expression: toString.constructor.prototype');
2429-
24302437
});
24312438

24322439
it('should NOT allow access to Function constructor in getter', function() {
@@ -2435,7 +2442,6 @@ describe('parser', function() {
24352442
}).toThrowMinErr(
24362443
'$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
24372444
'Expression: {}.toString.constructor("alert(1)")');
2438-
24392445
});
24402446

24412447
it('should NOT allow access to Function constructor in setter', function() {
@@ -2936,14 +2942,14 @@ describe('parser', function() {
29362942
});
29372943
});
29382944

2939-
it('should prevent the exploit', function() {
2940-
expect(function() {
2941-
scope.$eval('(1)[{0: "__proto__", 1: "__proto__", 2: "__proto__", 3: "safe", length: 4, toString: [].pop}].foo = 1');
2942-
}).toThrow();
2943-
if (!msie || msie > 10) {
2944-
expect((1)['__proto__'].foo).toBeUndefined();
2945-
}
2946-
});
2945+
it('should prevent the exploit', function() {
2946+
expect(function() {
2947+
scope.$eval('(1)[{0: "__proto__", 1: "__proto__", 2: "__proto__", 3: "safe", length: 4, toString: [].pop}].foo = 1');
2948+
}).toThrow();
2949+
if (!msie || msie > 10) {
2950+
expect((1)['__proto__'].foo).toBeUndefined();
2951+
}
2952+
});
29472953

29482954
it('should prevent the exploit', function() {
29492955
expect(function() {
@@ -3337,7 +3343,6 @@ describe('parser', function() {
33373343
expect($rootScope.$$watchers.length).toBe(1);
33383344
expect(log).toEqual([]);
33393345
}));
3340-
33413346
});
33423347
});
33433348

0 commit comments

Comments
 (0)