@@ -42,6 +42,17 @@ if ("I".toLowerCase() !== "i") {
42
42
lowercase = manualLowercase ;
43
43
}
44
44
45
+ // Run a function and disallow temporarly the use of the Function constructor
46
+ // This makes arbitrary code generation attacks way more complicated.
47
+ function runWithFunctionConstructorProtection ( fn ) {
48
+ var originalFunctionConstructor = Function . prototype . constructor ;
49
+ delete Function . prototype . constructor ;
50
+ var result = fn ( ) ;
51
+ // eslint-disable-next-line no-extend-native
52
+ Function . prototype . constructor = originalFunctionConstructor ;
53
+ return result ;
54
+ }
55
+
45
56
var jqLite , // delay binding since jQuery could be loaded after us.
46
57
toString = Object . prototype . toString ,
47
58
getPrototypeOf = Object . getPrototypeOf ,
@@ -1690,15 +1701,28 @@ ASTCompiler.prototype = {
1690
1701
extra +
1691
1702
this . watchFns ( ) +
1692
1703
"return fn;" ;
1704
+
1693
1705
// eslint-disable-next-line no-new-func
1694
- var fn = new Function (
1706
+ var wrappedFn = new Function (
1695
1707
"$filter" ,
1696
1708
"getStringValue" ,
1697
1709
"ifDefined" ,
1698
1710
"plus" ,
1699
1711
fnString
1700
1712
) ( this . $filter , getStringValue , ifDefined , plusFn ) ;
1701
1713
1714
+ var fn = function ( s , l , a , i ) {
1715
+ return runWithFunctionConstructorProtection ( function ( ) {
1716
+ return wrappedFn ( s , l , a , i ) ;
1717
+ } ) ;
1718
+ } ;
1719
+ fn . assign = function ( s , v , l ) {
1720
+ return runWithFunctionConstructorProtection ( function ( ) {
1721
+ return wrappedFn . assign ( s , v , l ) ;
1722
+ } ) ;
1723
+ } ;
1724
+ fn . inputs = wrappedFn . inputs ;
1725
+
1702
1726
this . state = this . stage = undefined ;
1703
1727
fn . ast = ast ;
1704
1728
fn . literal = isLiteral ( ast ) ;
@@ -1892,7 +1916,12 @@ ASTCompiler.prototype = {
1892
1916
) ;
1893
1917
} ,
1894
1918
intoId &&
1895
- self . lazyAssign ( intoId , self . nonComputedMember ( "l" , ast . name ) )
1919
+ function ( ) {
1920
+ self . if_ (
1921
+ self . hasOwnProperty_ ( "l" , ast . name ) ,
1922
+ self . lazyAssign ( intoId , self . nonComputedMember ( "l" , ast . name ) )
1923
+ ) ;
1924
+ }
1896
1925
) ;
1897
1926
recursionFn ( intoId ) ;
1898
1927
break ;
@@ -2166,7 +2195,7 @@ ASTCompiler.prototype = {
2166
2195
} ,
2167
2196
2168
2197
filter : function ( filterName ) {
2169
- if ( ! this . state . filters . hasOwnProperty ( filterName ) ) {
2198
+ if ( ! hasOwnProperty . call ( this . state . filters , filterName ) ) {
2170
2199
this . state . filters [ filterName ] = this . nextId ( true ) ;
2171
2200
}
2172
2201
return this . state . filters [ filterName ] ;
@@ -2258,7 +2287,7 @@ ASTCompiler.prototype = {
2258
2287
left +
2259
2288
"[" +
2260
2289
right +
2261
- "] : null )"
2290
+ "] : undefined )"
2262
2291
) ;
2263
2292
} ,
2264
2293
@@ -2375,7 +2404,7 @@ ASTInterpreter.prototype = {
2375
2404
forEach ( ast . body , function ( expression ) {
2376
2405
expressions . push ( self . recurse ( expression . expression ) ) ;
2377
2406
} ) ;
2378
- var fn =
2407
+ var wrappedFn =
2379
2408
ast . body . length === 0
2380
2409
? noop
2381
2410
: ast . body . length === 1
@@ -2389,10 +2418,22 @@ ASTInterpreter.prototype = {
2389
2418
} ;
2390
2419
2391
2420
if ( assign ) {
2392
- fn . assign = function ( scope , value , locals ) {
2421
+ wrappedFn . assign = function ( scope , value , locals ) {
2393
2422
return assign ( scope , locals , value ) ;
2394
2423
} ;
2395
2424
}
2425
+
2426
+ var fn = function ( scope , locals ) {
2427
+ return runWithFunctionConstructorProtection ( function ( ) {
2428
+ return wrappedFn ( scope , locals ) ;
2429
+ } ) ;
2430
+ } ;
2431
+ fn . assign = function ( scope , value , locals ) {
2432
+ return runWithFunctionConstructorProtection ( function ( ) {
2433
+ return wrappedFn . assign ( scope , value , locals ) ;
2434
+ } ) ;
2435
+ } ;
2436
+
2396
2437
if ( inputs ) {
2397
2438
fn . inputs = inputs ;
2398
2439
}
@@ -2720,7 +2761,10 @@ ASTInterpreter.prototype = {
2720
2761
if ( create && create !== 1 && base && base [ name ] == null ) {
2721
2762
base [ name ] = { } ;
2722
2763
}
2723
- var value = base ? base [ name ] : undefined ;
2764
+ var value ;
2765
+ if ( base && hasOwnProperty . call ( base , name ) ) {
2766
+ value = base ? base [ name ] : undefined ;
2767
+ }
2724
2768
if ( context ) {
2725
2769
return { context : base , name : name , value : value } ;
2726
2770
}
0 commit comments