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

Commit fd46fc8

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

File tree

2 files changed

+36
-30
lines changed

2 files changed

+36
-30
lines changed

src/ng/parse.js

+5-4
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

+31-26
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);
@@ -2115,16 +2124,16 @@ describe('parser', function() {
21152124
expect(scope.b).toEqual(234);
21162125
});
21172126

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

2122-
scope.$eval('0 ? a = 2 : a = 3');
2123-
expect(scope.a).toBe(3);
2131+
scope.$eval('0 ? a = 2 : a = 3');
2132+
expect(scope.a).toBe(3);
21242133

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

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

24222430
it('should not allow access to the Function prototype in the getter', function() {
@@ -2425,7 +2433,6 @@ describe('parser', function() {
24252433
}).toThrowMinErr(
24262434
'$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
24272435
'Expression: toString.constructor.prototype');
2428-
24292436
});
24302437

24312438
it('should NOT allow access to Function constructor in getter', function() {
@@ -2434,7 +2441,6 @@ describe('parser', function() {
24342441
}).toThrowMinErr(
24352442
'$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
24362443
'Expression: {}.toString.constructor("alert(1)")');
2437-
24382444
});
24392445

24402446
it('should NOT allow access to Function constructor in setter', function() {
@@ -2935,14 +2941,14 @@ describe('parser', function() {
29352941
});
29362942
});
29372943

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

29472953
it('should prevent the exploit', function() {
29482954
expect(function() {
@@ -3324,7 +3330,6 @@ describe('parser', function() {
33243330
expect($rootScope.$$watchers.length).toBe(1);
33253331
expect(log).toEqual([]);
33263332
}));
3327-
33283333
});
33293334
});
33303335

0 commit comments

Comments
 (0)