Browse Source

Added logic to skip variable declaration transformation
Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues

sanex3339 5 years ago
parent
commit
4dcff4eb4d

File diff suppressed because it is too large
+ 0 - 0
dist/index.browser.js


File diff suppressed because it is too large
+ 0 - 0
dist/index.cli.js


File diff suppressed because it is too large
+ 0 - 0
dist/index.js


+ 91 - 0
src/node-transformers/obfuscating-transformers/VariableDeclarationTransformer.ts

@@ -41,6 +41,11 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
      */
      */
     private readonly identifierObfuscatingReplacer: IIdentifierObfuscatingReplacer;
     private readonly identifierObfuscatingReplacer: IIdentifierObfuscatingReplacer;
 
 
+    /**
+     * @type {Map<TNodeWithLexicalScope, Set<string>>}
+     */
+    private readonly lexicalScopeProhibitedIdentifierNames: Map<TNodeWithLexicalScope, Set<string>> = new Map();
+
     /**
     /**
      * @type {TReplaceableIdentifiers}
      * @type {TReplaceableIdentifiers}
      */
      */
@@ -135,6 +140,10 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
         isGlobalDeclaration: boolean
         isGlobalDeclaration: boolean
     ): void {
     ): void {
         this.traverseDeclarationIdentifiers(variableDeclarationNode, (identifierNode: ESTree.Identifier) => {
         this.traverseDeclarationIdentifiers(variableDeclarationNode, (identifierNode: ESTree.Identifier) => {
+            if (this.isProhibitedVariableName(identifierNode, lexicalScopeNode)) {
+                return;
+            }
+
             if (isGlobalDeclaration) {
             if (isGlobalDeclaration) {
                 this.identifierObfuscatingReplacer.storeGlobalName(identifierNode.name, lexicalScopeNode);
                 this.identifierObfuscatingReplacer.storeGlobalName(identifierNode.name, lexicalScopeNode);
             } else {
             } else {
@@ -143,6 +152,88 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
         });
         });
     }
     }
 
 
+    /**
+     * @param {Identifier} identifierNode
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
+     */
+    private isProhibitedVariableName (
+        identifierNode: ESTree.Identifier,
+        lexicalScopeNode: TNodeWithLexicalScope
+    ): boolean {
+        let cachedLexicalScopeProhibitedIdentifierNames: Set<string> | undefined = this.lexicalScopeProhibitedIdentifierNames
+            .get(lexicalScopeNode);
+
+        if (cachedLexicalScopeProhibitedIdentifierNames?.has(identifierNode.name)) {
+            return true;
+        }
+
+        const isProhibitedVariableName: boolean = this.isProhibitedVariableNameUsingInObjectPatternNode(
+            identifierNode,
+            lexicalScopeNode
+        );
+
+        if (!isProhibitedVariableName) {
+            return false;
+        }
+
+        if (cachedLexicalScopeProhibitedIdentifierNames) {
+            cachedLexicalScopeProhibitedIdentifierNames.add(identifierNode.name);
+        } else {
+            cachedLexicalScopeProhibitedIdentifierNames = new Set([identifierNode.name]);
+            this.lexicalScopeProhibitedIdentifierNames.set(lexicalScopeNode, cachedLexicalScopeProhibitedIdentifierNames);
+        }
+
+        return true;
+    }
+
+    /**
+     * Should not rename identifiers that used inside destructing assignment without declaration
+     *
+     * var a, b; // should not be renamed
+     * ({a, b} = {a: 1, b: 2});
+     *
+     * @param {VariableDeclaration} identifierNode
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
+     */
+    private isProhibitedVariableNameUsingInObjectPatternNode (
+        identifierNode: ESTree.Identifier,
+        lexicalScopeNode: TNodeWithLexicalScope
+    ): boolean {
+        let isProhibitedVariableDeclaration: boolean = false;
+
+        estraverse.traverse(lexicalScopeNode, {
+            enter: (node: ESTree.Node, parentNode: ESTree.Node | null): void | estraverse.VisitorOption => {
+                if (
+                    NodeGuards.isObjectPatternNode(node)
+                    && parentNode
+                    && NodeGuards.isAssignmentExpressionNode(parentNode)
+                ) {
+                    const properties: ESTree.Property[] = node.properties;
+
+                    for (const property of properties) {
+                        if (property.computed) {
+                            continue;
+                        }
+
+                        if (!NodeGuards.isIdentifierNode(property.key)) {
+                            continue;
+                        }
+
+                        if (identifierNode.name !== property.key.name) {
+                            continue;
+                        }
+
+                        isProhibitedVariableDeclaration = true;
+
+                        return estraverse.VisitorOption.Break;
+                    }
+                }
+            }
+        });
+
+        return isProhibitedVariableDeclaration;
+    }
+
     /**
     /**
      * @param {VariableDeclaration} variableDeclarationNode
      * @param {VariableDeclaration} variableDeclarationNode
      * @param {TNodeWithLexicalScope} lexicalScopeNode
      * @param {TNodeWithLexicalScope} lexicalScopeNode

+ 8 - 0
src/node/NodeGuards.ts

@@ -32,6 +32,14 @@ export class NodeGuards {
         return node.type === NodeType.ArrowFunctionExpression;
         return node.type === NodeType.ArrowFunctionExpression;
     }
     }
 
 
+    /**
+     * @param {Node} node
+     * @returns {boolean}
+     */
+    public static isAssignmentExpressionNode (node: ESTree.Node): node is ESTree.AssignmentExpression {
+        return node.type === NodeType.AssignmentExpression;
+    }
+
     /**
     /**
      * @param {Node} node
      * @param {Node} node
      * @returns {boolean}
      * @returns {boolean}

+ 6 - 5
test/dev/dev.ts

@@ -7,11 +7,12 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
 
 
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
         `
         `
-            function foo () {
-                var bar;
-                if (false)
-                    bar = {baz: 1};
-            }
+            (function () {
+                var a, b;
+                ({a, b} = {a: 1, b: 2});
+            
+                console.log(a, b);
+            })();
         `,
         `,
         {
         {
             ...NO_ADDITIONAL_NODES_PRESET,
             ...NO_ADDITIONAL_NODES_PRESET,

+ 36 - 0
test/functional-tests/node-transformers/obfuscating-transformers/variable-declaration-transformer/VariableDeclarationTransformer.spec.ts

@@ -605,4 +605,40 @@ describe('VariableDeclarationTransformer', () => {
             assert.match(obfuscatedCode, objectRestRegExp);
             assert.match(obfuscatedCode, objectRestRegExp);
         });
         });
     });
     });
+
+    describe('Variant #18: destructing assignment without declaration', () => {
+        const variablesDeclaration: RegExp = /var *a, *b, *_0x[a-f0-9]{4,6};/;
+        const destructingAssignmentRegExp: RegExp = /\({ *a, *b *} *= *{ *'a' *: *0x1, *'b' *: *0x2 *}\);/;
+        const identifierAssignmentRegExp: RegExp = /_0x[a-f0-9]{4,6} *= *0x3;/;
+        const variablesUsageRegExp: RegExp = /console\['log']\(a, *b, *_0x[a-f0-9]{4,6}\);/;
+
+        let obfuscatedCode: string;
+
+        before(() => {
+            const code: string = readFileAsString(__dirname + '/fixtures/destructing-assignment-without-declaration.js');
+
+            obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                code,
+                {
+                    ...NO_ADDITIONAL_NODES_PRESET
+                }
+            ).getObfuscatedCode();
+        });
+
+        it('match #1: should transform variables declaration', () => {
+            assert.match(obfuscatedCode, variablesDeclaration);
+        });
+
+        it('match #2: should transform destructing assignment without declaration', () => {
+            assert.match(obfuscatedCode, destructingAssignmentRegExp);
+        });
+
+        it('match #3: should transform identifier assignment', () => {
+            assert.match(obfuscatedCode, identifierAssignmentRegExp);
+        });
+
+        it('match #4: should transform variables usage', () => {
+            assert.match(obfuscatedCode, variablesUsageRegExp);
+        });
+    });
 });
 });

+ 7 - 0
test/functional-tests/node-transformers/obfuscating-transformers/variable-declaration-transformer/fixtures/destructing-assignment-without-declaration.js

@@ -0,0 +1,7 @@
+(function () {
+    var a, b, c;
+    ({a, b} = {a: 1, b: 2});
+    c = 3;
+
+    console.log(a, b, c);
+})();

Some files were not shown because too many files changed in this diff