@@ -854,6 +854,10 @@ function setter(obj, path, setValue, fullExp) {
854854
855855var getterFnCache = createMap ( ) ;
856856
857+ function isPossiblyDangerousMemberName ( name ) {
858+ return name == 'constructor' ;
859+ }
860+
857861/**
858862 * Implementation of the "Black Hole" variant from:
859863 * - http://jsperf.com/angularjs-parse-getter/4
@@ -865,33 +869,47 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp) {
865869 ensureSafeMemberName ( key2 , fullExp ) ;
866870 ensureSafeMemberName ( key3 , fullExp ) ;
867871 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 ;
868880
869881 return function cspSafeGetter ( scope , locals ) {
870882 var pathVal = ( locals && locals . hasOwnProperty ( key0 ) ) ? locals : scope ;
871883
872884 if ( pathVal == null ) return pathVal ;
873- pathVal = pathVal [ key0 ] ;
885+ pathVal = eso0 ( pathVal [ key0 ] ) ;
874886
875887 if ( ! key1 ) return pathVal ;
876888 if ( pathVal == null ) return undefined ;
877- pathVal = pathVal [ key1 ] ;
889+ pathVal = eso1 ( pathVal [ key1 ] ) ;
878890
879891 if ( ! key2 ) return pathVal ;
880892 if ( pathVal == null ) return undefined ;
881- pathVal = pathVal [ key2 ] ;
893+ pathVal = eso2 ( pathVal [ key2 ] ) ;
882894
883895 if ( ! key3 ) return pathVal ;
884896 if ( pathVal == null ) return undefined ;
885- pathVal = pathVal [ key3 ] ;
897+ pathVal = eso3 ( pathVal [ key3 ] ) ;
886898
887899 if ( ! key4 ) return pathVal ;
888900 if ( pathVal == null ) return undefined ;
889- pathVal = pathVal [ key4 ] ;
901+ pathVal = eso4 ( pathVal [ key4 ] ) ;
890902
891903 return pathVal ;
892904 } ;
893905}
894906
907+ function getterFnWithEnsureSafeObject ( fn , fullExpression ) {
908+ return function ( s , l ) {
909+ return fn ( s , l , ensureSafeObject , fullExpression ) ;
910+ } ;
911+ }
912+
895913function getterFn ( path , options , fullExp ) {
896914 var fn = getterFnCache [ path ] ;
897915
@@ -919,22 +937,30 @@ function getterFn(path, options, fullExp) {
919937 }
920938 } else {
921939 var code = '' ;
940+ var needsEnsureSafeObject = false ;
922941 forEach ( pathKeys , function ( key , index ) {
923942 ensureSafeMemberName ( key , fullExp ) ;
924- code += 'if(s == null) return undefined;\n' +
925- 's=' + ( index
943+ var lookupJs = ( index
926944 // we simply dereference 's' on any .dot notation
927945 ? 's'
928946 // 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' ;
930954 } ) ;
931955 code += 'return s;' ;
932956
933957 /* 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
935959 /* jshint +W054 */
936960 evaledFnGetter . toString = valueFn ( code ) ;
937-
961+ if ( needsEnsureSafeObject ) {
962+ evaledFnGetter = getterFnWithEnsureSafeObject ( evaledFnGetter , fullExp ) ;
963+ }
938964 fn = evaledFnGetter ;
939965 }
940966
0 commit comments