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

Commit 3b1a4fe

Browse files
dozingcatIgorMinar
authored andcommitted
fix($parse): fix CSP nested property evaluation, and issue that prevented its tests from failing
cspSafeGetterFn incorrectly returned undefined if any of its key parameters were undefined. This wasn't caught by the $parse unit tests because of a timing problem where $ParseProvider was reading the CSP flag before the tests manually set it, so the CSP property evaluation tests never ran. Add test that verifies evaluation of nested properties of multiple lengths. Closes #5591 Closes #5592
1 parent 9569778 commit 3b1a4fe

File tree

2 files changed

+74
-13
lines changed

2 files changed

+74
-13
lines changed

src/ng/parse.js

+16-8
Original file line numberDiff line numberDiff line change
@@ -894,16 +894,20 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
894894
if (pathVal == null) return pathVal;
895895
pathVal = pathVal[key0];
896896

897-
if (pathVal == null) return key1 ? undefined : pathVal;
897+
if (!key1) return pathVal;
898+
if (pathVal == null) return undefined;
898899
pathVal = pathVal[key1];
899900

900-
if (pathVal == null) return key2 ? undefined : pathVal;
901+
if (!key2) return pathVal;
902+
if (pathVal == null) return undefined;
901903
pathVal = pathVal[key2];
902904

903-
if (pathVal == null) return key3 ? undefined : pathVal;
905+
if (!key3) return pathVal;
906+
if (pathVal == null) return undefined;
904907
pathVal = pathVal[key3];
905908

906-
if (pathVal == null) return key4 ? undefined : pathVal;
909+
if (!key4) return pathVal;
910+
if (pathVal == null) return undefined;
907911
pathVal = pathVal[key4];
908912

909913
return pathVal;
@@ -924,8 +928,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
924928
}
925929
pathVal = pathVal.$$v;
926930
}
927-
if (pathVal == null) return key1 ? undefined : pathVal;
928931

932+
if (!key1) return pathVal;
933+
if (pathVal == null) return undefined;
929934
pathVal = pathVal[key1];
930935
if (pathVal && pathVal.then) {
931936
promiseWarning(fullExp);
@@ -936,8 +941,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
936941
}
937942
pathVal = pathVal.$$v;
938943
}
939-
if (pathVal == null) return key2 ? undefined : pathVal;
940944

945+
if (!key2) return pathVal;
946+
if (pathVal == null) return undefined;
941947
pathVal = pathVal[key2];
942948
if (pathVal && pathVal.then) {
943949
promiseWarning(fullExp);
@@ -948,8 +954,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
948954
}
949955
pathVal = pathVal.$$v;
950956
}
951-
if (pathVal == null) return key3 ? undefined : pathVal;
952957

958+
if (!key3) return pathVal;
959+
if (pathVal == null) return undefined;
953960
pathVal = pathVal[key3];
954961
if (pathVal && pathVal.then) {
955962
promiseWarning(fullExp);
@@ -960,8 +967,9 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
960967
}
961968
pathVal = pathVal.$$v;
962969
}
963-
if (pathVal == null) return key4 ? undefined : pathVal;
964970

971+
if (!key4) return pathVal;
972+
if (pathVal == null) return undefined;
965973
pathVal = pathVal[key4];
966974
if (pathVal && pathVal.then) {
967975
promiseWarning(fullExp);

test/ng/parseSpec.js

+58-5
Original file line numberDiff line numberDiff line change
@@ -204,13 +204,24 @@ describe('parser', function() {
204204

205205
describe('csp: ' + cspEnabled + ", unwrapPromises: " + unwrapPromisesEnabled, function() {
206206

207-
beforeEach(module(function ($parseProvider) {
207+
var originalSecurityPolicy;
208+
209+
210+
beforeEach(function() {
211+
originalSecurityPolicy = window.document.securityPolicy;
212+
window.document.securityPolicy = {isActive : cspEnabled};
213+
});
214+
215+
afterEach(function() {
216+
window.document.securityPolicy = originalSecurityPolicy;
217+
});
218+
219+
beforeEach(module(function ($parseProvider, $provide) {
208220
$parseProvider.unwrapPromises(unwrapPromisesEnabled);
209221
}));
210222

211-
beforeEach(inject(function ($rootScope, $sniffer) {
223+
beforeEach(inject(function ($rootScope) {
212224
scope = $rootScope;
213-
$sniffer.csp = cspEnabled;
214225
}));
215226

216227
it('should parse expressions', function() {
@@ -344,6 +355,25 @@ describe('parser', function() {
344355
expect(scope.$eval("a.b.c.d.e.f.g.h.i.j.k.l.m.n", scope)).toBe('nooo!');
345356
});
346357

358+
forEach([2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 42, 99], function(pathLength) {
359+
it('should resolve nested paths of length ' + pathLength, function() {
360+
// Create a nested object {x2: {x3: {x4: ... {x[n]: 42} ... }}}.
361+
var obj = 42;
362+
for (var i = pathLength; i >= 2; i--) {
363+
var newObj = {};
364+
newObj['x' + i] = obj;
365+
obj = newObj;
366+
}
367+
// Assign to x1 and build path 'x1.x2.x3. ... .x[n]' to access the final value.
368+
scope.x1 = obj;
369+
var path = 'x1';
370+
for (var i = 2; i <= pathLength; i++) {
371+
path += '.x' + i;
372+
}
373+
expect(scope.$eval(path)).toBe(42);
374+
});
375+
});
376+
347377
it('should be forgiving', function() {
348378
scope.a = {b: 23};
349379
expect(scope.$eval('b')).toBeUndefined();
@@ -1069,6 +1099,17 @@ describe('parser', function() {
10691099

10701100
var $log;
10711101
var PROMISE_WARNING_REGEXP = /\[\$parse\] Promise found in the expression `[^`]+`. Automatic unwrapping of promises in Angular expressions is deprecated\./;
1102+
var originalSecurityPolicy;
1103+
1104+
1105+
beforeEach(function() {
1106+
originalSecurityPolicy = window.document.securityPolicy;
1107+
window.document.securityPolicy = {isActive : cspEnabled};
1108+
});
1109+
1110+
afterEach(function() {
1111+
window.document.securityPolicy = originalSecurityPolicy;
1112+
});
10721113

10731114
beforeEach(module(function($parseProvider) {
10741115
$parseProvider.unwrapPromises(true);
@@ -1142,15 +1183,27 @@ describe('parser', function() {
11421183

11431184
describe('csp ' + cspEnabled, function() {
11441185

1186+
var originalSecurityPolicy;
1187+
1188+
1189+
beforeEach(function() {
1190+
originalSecurityPolicy = window.document.securityPolicy;
1191+
window.document.securityPolicy = {isActive : cspEnabled};
1192+
});
1193+
1194+
afterEach(function() {
1195+
window.document.securityPolicy = originalSecurityPolicy;
1196+
});
1197+
1198+
11451199
beforeEach(module(function($parseProvider) {
11461200
$parseProvider.unwrapPromises(true);
11471201
$parseProvider.logPromiseWarnings(false);
11481202
}));
11491203

11501204

1151-
beforeEach(inject(function($rootScope, $sniffer, $q) {
1205+
beforeEach(inject(function($rootScope, $q) {
11521206
scope = $rootScope;
1153-
$sniffer.csp = cspEnabled;
11541207

11551208
q = $q;
11561209
deferred = q.defer();

0 commit comments

Comments
 (0)