@@ -75,6 +75,18 @@ const StatementDebug = false;
7575
7676const MAX_INTERVALS = 16 ;
7777
78+ const NativePrototypes = [
79+ Object . prototype ,
80+ Function . prototype ,
81+ Array . prototype ,
82+ String . prototype ,
83+ Number . prototype ,
84+ Boolean . prototype ,
85+ ] ;
86+ const NativePrototypesSet = new Set ( NativePrototypes ) ;
87+
88+ NativePrototypes . forEach ( Object . preventExtensions ) ;
89+
7890const StorageType = {
7991 Private : "private" ,
8092 Public : "public" ,
@@ -206,6 +218,20 @@ const Keywords = {
206218 styled : true ,
207219} ;
208220
221+ const filterEthersUtils = ( utils ) => {
222+ [
223+ "checkProperties" ,
224+ "deepCopy" ,
225+ "defineReadOnly" ,
226+ "getStatic" ,
227+ "resolveProperties" ,
228+ "shallowCopy" ,
229+ ] . forEach ( ( key ) => {
230+ delete utils [ key ] ;
231+ } ) ;
232+ return utils ;
233+ } ;
234+
209235const GlobalInjected = deepFreeze (
210236 cloneDeep ( {
211237 // Functions
@@ -231,7 +257,7 @@ const GlobalInjected = deepFreeze(
231257 verify : nacl . verify ,
232258 } ,
233259 ethers : {
234- utils : ethers . utils ,
260+ utils : filterEthersUtils ( deepCopy ( ethers . utils ) ) ,
235261 BigNumber : ethers . BigNumber ,
236262 Contract : ethers . Contract ,
237263 providers : ethers . providers ,
@@ -299,13 +325,21 @@ const assertNotReservedKey = (key) => {
299325 }
300326} ;
301327
302- const assertNotReactObject = ( o ) => {
328+ const assertNotNativePrototype = ( o ) => {
329+ if ( NativePrototypesSet . has ( o ) ) {
330+ throw new Error ( "Native prototypes shouldn't be used" ) ;
331+ }
332+ } ;
333+
334+ const assertDereferenceableObject = ( o ) => {
335+ assertNotNativePrototype ( o ) ;
303336 if ( isReactObject ( o ) ) {
304- throw new Error ( "React objects shouldn't dereferenced" ) ;
337+ throw new Error ( "React objects shouldn't be dereferenced" ) ;
305338 }
306339} ;
307340
308341const assertValidObject = ( o ) => {
342+ assertDereferenceableObject ( o ) ;
309343 if ( o !== null && typeof o === "object" ) {
310344 Object . entries ( o ) . forEach ( ( [ key , value ] ) => {
311345 assertNotReservedKey ( key ) ;
@@ -475,6 +509,7 @@ class VmStack {
475509 executeExpression ( code ) {
476510 ExpressionDebug && console . log ( "Executing code:" , code ?. type ) ;
477511 const res = this . executeExpressionInternal ( code ) ;
512+ assertNotNativePrototype ( res ) ;
478513 ExpressionDebug && console . log ( code ?. type , res ) ;
479514 return res ;
480515 }
@@ -642,6 +677,14 @@ class VmStack {
642677 : "about:blank" ;
643678 }
644679 } ) ;
680+ } else if ( basicElement === "set" ) {
681+ if (
682+ attributes . attributeName === "href" ||
683+ attributes . attributeName === "xlink:href" ||
684+ attributes . attributeName === "is"
685+ ) {
686+ return < > </ > ;
687+ }
645688 } else if ( element === "Widget" ) {
646689 attributes . depth = this . vm . depth + 1 ;
647690 attributes . config = [ attributes . config , ...this . vm . widgetConfigs ] . filter (
@@ -779,7 +822,7 @@ class VmStack {
779822 throw new Error ( `The top object should be ${ StakeKey } ` ) ;
780823 }
781824 const obj = this . stack . findObj ( key ) ?? this . stack . state ;
782- assertNotReactObject ( obj ) ;
825+ assertDereferenceableObject ( obj ) ;
783826 if ( obj === this . stack . state ) {
784827 if ( Keywords . hasOwnProperty ( key ) ) {
785828 if ( options ?. left ) {
@@ -819,7 +862,7 @@ class VmStack {
819862 }
820863 }
821864 const obj = this . executeExpression ( code . object ) ;
822- assertNotReactObject ( obj ) ;
865+ assertDereferenceableObject ( obj ) ;
823866 const key = this . resolveKey ( code . property , code . computed ) ;
824867 return { obj, key } ;
825868 } else {
@@ -1005,7 +1048,7 @@ class VmStack {
10051048 object [ key ] = this . executeExpression ( property . value ) ;
10061049 } else if ( property . type === "SpreadElement" ) {
10071050 const value = this . executeExpression ( property . argument ) ;
1008- assertNotReactObject ( value ) ;
1051+ assertDereferenceableObject ( value ) ;
10091052 Object . assign ( object , value ) ;
10101053 } else {
10111054 throw new Error ( "Unknown property type: " + property . type ) ;
@@ -1187,7 +1230,7 @@ class VmStack {
11871230 if ( pattern . type === "Identifier" ) {
11881231 this . stack . state [ pattern . name ] = value ;
11891232 } else if ( pattern . type === "ArrayPattern" ) {
1190- assertNotReactObject ( value ) ;
1233+ assertDereferenceableObject ( value ) ;
11911234 pattern . elements . forEach ( ( element , i ) => {
11921235 if ( element . type === "RestElement" ) {
11931236 this . stackDeclare ( element . argument , value . slice ( i ) ) ;
@@ -1196,7 +1239,7 @@ class VmStack {
11961239 }
11971240 } ) ;
11981241 } else if ( pattern . type === "ObjectPattern" ) {
1199- assertNotReactObject ( value ) ;
1242+ assertDereferenceableObject ( value ) ;
12001243 const seen = new Set ( ) ;
12011244 pattern . properties . forEach ( ( property ) => {
12021245 if ( property . type === "RestElement" ) {
@@ -1281,7 +1324,7 @@ class VmStack {
12811324 } else if ( token . type === "ForOfStatement" ) {
12821325 const stack = this . newStack ( ) ;
12831326 const right = stack . executeExpression ( token . right ) ;
1284- assertNotReactObject ( right ) ;
1327+ assertDereferenceableObject ( right ) ;
12851328 for ( const value of right ) {
12861329 if ( this . vm . loopLimit -- <= 0 ) {
12871330 throw new Error ( "Exceeded loop limit" ) ;
@@ -1643,7 +1686,7 @@ export default class VM {
16431686 if ( args . length < 1 ) {
16441687 throw new Error ( "Missing argument 'obj' for JSON.stringify" ) ;
16451688 }
1646- assertNotReactObject ( args [ 0 ] ) ;
1689+ assertDereferenceableObject ( args [ 0 ] ) ;
16471690 return JSON . stringify ( args [ 0 ] , args [ 1 ] , args [ 2 ] ) ;
16481691 } ,
16491692 parse : ( ...args ) => {
@@ -1665,25 +1708,25 @@ export default class VM {
16651708 if ( args . length < 1 ) {
16661709 throw new Error ( "Missing argument 'obj' for Object.keys" ) ;
16671710 }
1668- assertNotReactObject ( args [ 0 ] ) ;
1711+ assertDereferenceableObject ( args [ 0 ] ) ;
16691712 return Object . keys ( args [ 0 ] ) ;
16701713 } ,
16711714 values : ( ...args ) => {
16721715 if ( args . length < 1 ) {
16731716 throw new Error ( "Missing argument 'obj' for Object.values" ) ;
16741717 }
1675- assertNotReactObject ( args [ 0 ] ) ;
1718+ assertDereferenceableObject ( args [ 0 ] ) ;
16761719 return Object . values ( args [ 0 ] ) ;
16771720 } ,
16781721 entries : ( ...args ) => {
16791722 if ( args . length < 1 ) {
16801723 throw new Error ( "Missing argument 'obj' for Object.entries" ) ;
16811724 }
1682- assertNotReactObject ( args [ 0 ] ) ;
1725+ assertDereferenceableObject ( args [ 0 ] ) ;
16831726 return Object . entries ( args [ 0 ] ) ;
16841727 } ,
16851728 assign : ( ...args ) => {
1686- args . forEach ( ( arg ) => assertNotReactObject ( arg ) ) ;
1729+ args . forEach ( ( arg ) => assertDereferenceableObject ( arg ) ) ;
16871730 const obj = Object . assign ( ...args ) ;
16881731 assertValidObject ( obj ) ;
16891732 return obj ;
0 commit comments