X Tutup
Skip to content

Renaming constant variable in class static block results in TypeError #1141

@nicolejrkim

Description

@nicolejrkim

According to the ECMAScript specification, running a JavaScript program class x { static { const x = { x } = 0 ; } } is expected to result in ReferenceError but after obfuscating the JavaScript program, it results in TypeError.

Expected Behavior

Running the following JavaScript code using Node.js results in ReferenceError.

class x { static { const x = { x } = 0 ; } }

obfuscator_referenceerror

Current Behavior

However, as shown below, running the obfuscated code using Node.js results in TypeError.

Obfuscated code

class x{static{const _0x2340e4={x}=0x0;}}

obfuscator_typeerror

In summary, obfuscated code results in TypeError, because obfuscator have renamed constant variable in class static block. (e.g. x to _0x2340e4)

  1. Original code and obfuscated code both evaluates { x } = 0 and {x}=0x0 to initialize x in x = { x } = 0 and _0x2340e4 in _0x2340e4={x}=0x0.
  2. When resolving x in {x}, the original code resolves to x in const x and the obfuscated code resolves to x in class x.
  3. In case of the original code,
    1. ReferenceError exception arises because it tries to set mutable binding for uninitialized x, which refers to const x.
  4. In case of the obfuscated code,
    1. the TypeError exception arises because it tries to change the value of an immutable binding x, which refers to class x.

Steps to Reproduce

  1. Obfuscate the following program using https://obfuscator.io.
  2. Run the following program using Node.js v18.13.0.

Your Environment

Stack trace

Minimal working example that will help to reproduce issue


Below is a detailed explanation using ECMAScript specification.

Evaluation of class x { static { const x = { x } = 0 ; } } is done by following algorithms.

1. Operation ClassDefinitionEvaluation of ECMAScript specification

In step 3, the algorithm creates an immutable binding of x.

In step 27, the algorithm initializes the binding of x with F.

obs_3

obs_4

In step 31-b, the algorithm calls Call(initializer,receiver).
where initializer represents the const x = { x } = 0 ; and receiver represents the evaluation result of ClassDefinition of x.

obs_5

2. Operation ClassStaticBlockBody.EvaluateClassStaticBlockBody of the ECMAScript specification

This step evaluates the ClassStaticBlockBody, which represents const x = { x } = 0 ; and creates binding of variables in ClassStaticBlockBody in class environment.

In step 1, the algorithm calls FunctionDeclarationInstantiation(functionObject, <<>>), where functionObject represents the const x = { x } = 0 ;.
This step creates binding of x, which represents the constant variable name const x.

In step 2, the algorithm calls the evaluation of ClassStaticBlockStatementList, where ClassStaticBlockStatementList represents const x = { x } = 0 ;

obs_10

3. Evaluation of LexicalBinding in ECMAScript specification

LexicalBinding represents x = {x} = 0, and it can be divided into BindingIdentifier x and Initializer = {x} = 0.

This algorithm intends to resolve bindingId and evaluate Initializer to initialize binding at step 5.

Note that binding for the constant variable x is not initialized until it reaches step 5.

In step 4, the algorithm calls the evaluation of Initializer.

obs_11

4. Evaluation of AssignmentExpression in ECMAScript specification

AssignmentExpression represents {x} = 0, and it can be divided into LeftHandSideExpression {x} and AssignmentExpression 0.

In step 5, the algorithm calls DestructuringAssignmentEvaluation(value) of assignmentPattern, where value represents 0 and assignmentPattern represents {x}.

obs_12

Then, DestructuringAssignmentEvaluation calls PropertyDestructuringAssignmentEvaluation(value), where value represents 0.

5. Operation AssignmentProperty.PropertyDestructuringAssignmentEvaluation in ECMASCript specification

In step 2, the algorithm resolves x as the constant variable x.

In step 5, the algorithm calls PutValue(V, W), where V represents a reference of the constant variable x and W rerpresents undefined.

obs_14

Then, PutValue calls SetMutableBinding(N, V, S) of base, where base represents the environment that binding of constant variable x is stored, N represents x, V represents undefined, and S represents True.

6. Operation SetMutableBinding in ECMAScript specification

In step 3, the algorithm throws a ReferenceError exception, because the binding for N, which is x in envRec has not yet been initialized.

In detail, the x in envRec refers the x in const x. Therefore, it has not been initialized.

obs_16


In comparison, the evaluation of the obfuscated JavaScript program, class x{static{const _0x2340e4={x}=0x0;}}, is similar but different in following steps.

2. Operation ClassStaticBlockBody.EvaluateClassStaticBlockBody of the ECMAScript specification

In step 1, the algorithm creates an immutable binding of _0x2340e4 in class environment.

In step 2, the algorithm calls the evaluation of ClassStaticBlockStatementList, where ClassStaticBlockStatementList represents const _0x2340e4 = { x } = 0x0 ;.

obs_10

5. Operation AssignmentProperty.PropertyDestructuringAssignmentEvaluation in ECMASCript specification

In step 2, the algorithm resolves x as the class x.

In step 5, the algorithm calls PutValue(V, W), where V represents a reference of the class x.

obs_14

Then, PutValue calls SetMutableBinding(N, V, S) of base, where base represents the environment that binding of class x is stored.

6. Operation SetMutableBinding in ECMAScript specification

In step 5-b, the algorithm throws a TypeError exception, because the binding for x in envRec is an immutable binding (class binding).

Since this is an attempt to change the value of an immuatble binding, the algorithm throws TypeError exception.

obs_16

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      X Tutup