@@ -854,6 +854,10 @@ function setter(obj, path, setValue, fullExp) {
854
854
855
855
var getterFnCache = createMap ( ) ;
856
856
857
+ function isPossiblyDangerousMemberName ( name ) {
858
+ return name == 'constructor' ;
859
+ }
860
+
857
861
/**
858
862
* Implementation of the "Black Hole" variant from:
859
863
* - http://jsperf.com/angularjs-parse-getter/4
@@ -865,33 +869,47 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp) {
865
869
ensureSafeMemberName ( key2 , fullExp ) ;
866
870
ensureSafeMemberName ( key3 , fullExp ) ;
867
871
ensureSafeMemberName ( key4 , fullExp ) ;
872
+ var eso = function ( o ) {
873
+ return ensureSafeObject ( o , fullExp ) ;
874
+ } ;
875
+ var eso0 = isPossiblyDangerousMemberName ( key0 ) ? eso : identity ;
876
+ var eso1 = isPossiblyDangerousMemberName ( key1 ) ? eso : identity ;
877
+ var eso2 = isPossiblyDangerousMemberName ( key2 ) ? eso : identity ;
878
+ var eso3 = isPossiblyDangerousMemberName ( key3 ) ? eso : identity ;
879
+ var eso4 = isPossiblyDangerousMemberName ( key4 ) ? eso : identity ;
868
880
869
881
return function cspSafeGetter ( scope , locals ) {
870
882
var pathVal = ( locals && locals . hasOwnProperty ( key0 ) ) ? locals : scope ;
871
883
872
884
if ( pathVal == null ) return pathVal ;
873
- pathVal = pathVal [ key0 ] ;
885
+ pathVal = eso0 ( pathVal [ key0 ] ) ;
874
886
875
887
if ( ! key1 ) return pathVal ;
876
888
if ( pathVal == null ) return undefined ;
877
- pathVal = pathVal [ key1 ] ;
889
+ pathVal = eso1 ( pathVal [ key1 ] ) ;
878
890
879
891
if ( ! key2 ) return pathVal ;
880
892
if ( pathVal == null ) return undefined ;
881
- pathVal = pathVal [ key2 ] ;
893
+ pathVal = eso2 ( pathVal [ key2 ] ) ;
882
894
883
895
if ( ! key3 ) return pathVal ;
884
896
if ( pathVal == null ) return undefined ;
885
- pathVal = pathVal [ key3 ] ;
897
+ pathVal = eso3 ( pathVal [ key3 ] ) ;
886
898
887
899
if ( ! key4 ) return pathVal ;
888
900
if ( pathVal == null ) return undefined ;
889
- pathVal = pathVal [ key4 ] ;
901
+ pathVal = eso4 ( pathVal [ key4 ] ) ;
890
902
891
903
return pathVal ;
892
904
} ;
893
905
}
894
906
907
+ function getterFnWithEnsureSafeObject ( fn , fullExpression ) {
908
+ return function ( s , l ) {
909
+ return fn ( s , l , ensureSafeObject , fullExpression ) ;
910
+ } ;
911
+ }
912
+
895
913
function getterFn ( path , options , fullExp ) {
896
914
var fn = getterFnCache [ path ] ;
897
915
@@ -919,22 +937,30 @@ function getterFn(path, options, fullExp) {
919
937
}
920
938
} else {
921
939
var code = '' ;
940
+ var needsEnsureSafeObject = false ;
922
941
forEach ( pathKeys , function ( key , index ) {
923
942
ensureSafeMemberName ( key , fullExp ) ;
924
- code += 'if(s == null) return undefined;\n' +
925
- 's=' + ( index
943
+ var lookupJs = ( index
926
944
// we simply dereference 's' on any .dot notation
927
945
? 's'
928
946
// but if we are first then we check locals first, and if so read it first
929
- : '((l&&l.hasOwnProperty("' + key + '"))?l:s)' ) + '.' + key + ';\n' ;
947
+ : '((l&&l.hasOwnProperty("' + key + '"))?l:s)' ) + '.' + key ;
948
+ if ( isPossiblyDangerousMemberName ( key ) ) {
949
+ lookupJs = 'eso(' + lookupJs + ', fe)' ;
950
+ needsEnsureSafeObject = true ;
951
+ }
952
+ code += 'if(s == null) return undefined;\n' +
953
+ 's=' + lookupJs + ';\n' ;
930
954
} ) ;
931
955
code += 'return s;' ;
932
956
933
957
/* jshint -W054 */
934
- var evaledFnGetter = new Function ( 's' , 'l' , code ) ; // s=scope, l=locals
958
+ var evaledFnGetter = new Function ( 's' , 'l' , 'eso' , 'fe' , code ) ; // s=scope, l=locals, eso=ensureSafeObject
935
959
/* jshint +W054 */
936
960
evaledFnGetter . toString = valueFn ( code ) ;
937
-
961
+ if ( needsEnsureSafeObject ) {
962
+ evaledFnGetter = getterFnWithEnsureSafeObject ( evaledFnGetter , fullExp ) ;
963
+ }
938
964
fn = evaledFnGetter ;
939
965
}
940
966
0 commit comments