diff --git a/CHANGELOG.md b/CHANGELOG.md index fa22546c..f5366d17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ Change Log +v3.2.3 +--- +* Fixed missing transformation of string array calls in some cases +* Fixed generation of reserved identifier names like `Map` or `Set` for `mangled` and `mangled-shuffled` identifier names generators + v3.2.2 --- * Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1039 diff --git a/package.json b/package.json index 201c7e71..027a1d22 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "javascript-obfuscator", - "version": "3.2.2", + "version": "3.2.3", "description": "JavaScript obfuscator", "keywords": [ "obfuscator", diff --git a/src/node-transformers/rename-properties-transformers/replacer/ReservedDomProperties.json b/src/constants/ReservedDomProperties.json similarity index 100% rename from src/node-transformers/rename-properties-transformers/replacer/ReservedDomProperties.json rename to src/constants/ReservedDomProperties.json diff --git a/src/constants/ReservedIdentifierNames.ts b/src/constants/ReservedIdentifierNames.ts new file mode 100644 index 00000000..9ba8e37d --- /dev/null +++ b/src/constants/ReservedIdentifierNames.ts @@ -0,0 +1,11 @@ +export const reservedIdentifierNames = [ + // reserved identifiers + 'byte', 'case', 'char', 'do', 'else', 'enum', 'eval', 'for', 'goto', + 'if', 'in', 'int', 'let', 'long', 'new', 'null', 'this', 'true', 'try', + 'var', 'void', 'with', + + // reserved global object identifiers + 'Array', 'Attr', 'Audio', 'Blob', 'Cache', 'Date', 'Error', 'Event', + 'Feed', 'File', 'Hz', 'Image', 'Intl', 'Lock', 'Map', 'Math', 'Node', + 'Proxy', 'Range', 'Rect', 'Set', 'Table', 'Text', 'Touch' +]; diff --git a/src/generators/identifier-names-generators/AbstractIdentifierNamesGenerator.ts b/src/generators/identifier-names-generators/AbstractIdentifierNamesGenerator.ts index 5dc97070..f9ab69fe 100644 --- a/src/generators/identifier-names-generators/AbstractIdentifierNamesGenerator.ts +++ b/src/generators/identifier-names-generators/AbstractIdentifierNamesGenerator.ts @@ -79,7 +79,8 @@ export abstract class AbstractIdentifierNamesGenerator implements IIdentifierNam * @returns {boolean} */ public isValidIdentifierName (name: string): boolean { - return this.notReservedName(name) && !this.preservedNamesSet.has(name); + return !this.isReservedName(name) + && !this.preservedNamesSet.has(name); } /** @@ -112,12 +113,12 @@ export abstract class AbstractIdentifierNamesGenerator implements IIdentifierNam * @param {string} name * @returns {boolean} */ - private notReservedName (name: string): boolean { + private isReservedName (name: string): boolean { return this.options.reservedNames.length - ? !this.options.reservedNames.some((reservedName: string) => + ? this.options.reservedNames.some((reservedName: string) => new RegExp(reservedName, 'g').exec(name) !== null ) - : true; + : false; } diff --git a/src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts b/src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts index c38d403d..29bfd06c 100644 --- a/src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts +++ b/src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts @@ -7,9 +7,10 @@ import { IOptions } from '../../interfaces/options/IOptions'; import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator'; import { ISetUtils } from '../../interfaces/utils/ISetUtils'; -import { numbersString } from '../../constants/NumbersString'; import { alphabetString } from '../../constants/AlphabetString'; import { alphabetStringUppercase } from '../../constants/AlphabetStringUppercase'; +import { numbersString } from '../../constants/NumbersString'; +import { reservedIdentifierNames } from '../../constants/ReservedIdentifierNames'; import { AbstractIdentifierNamesGenerator } from './AbstractIdentifierNamesGenerator'; import { NodeLexicalScopeUtils } from '../../node/NodeLexicalScopeUtils'; @@ -40,14 +41,11 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene /** * Reserved JS words with length of 2-4 symbols that can be possible generated with this replacer + * + reserved DOM names like `Set`, `Map`, `Date`, etc * * @type {Set} */ - private static readonly reservedNamesSet: Set = new Set([ - 'byte', 'case', 'char', 'do', 'else', 'enum', 'eval', 'for', 'goto', - 'if', 'in', 'int', 'let', 'long', 'new', 'null', 'this', 'true', 'try', - 'var', 'void', 'with' - ]); + private static readonly reservedNamesSet: Set = new Set(reservedIdentifierNames); /** * @type {WeakMap} diff --git a/src/node-transformers/control-flow-transformers/StringArrayControlFlowTransformer.ts b/src/node-transformers/control-flow-transformers/StringArrayControlFlowTransformer.ts index 97438038..ab9cd7b3 100644 --- a/src/node-transformers/control-flow-transformers/StringArrayControlFlowTransformer.ts +++ b/src/node-transformers/control-flow-transformers/StringArrayControlFlowTransformer.ts @@ -11,6 +11,7 @@ import { } from '../../types/container/node-transformers/TControlFlowStorageFactoryCreator'; import { TNodeWithStatements } from '../../types/node/TNodeWithStatements'; +import { IControlFlowStorage } from '../../interfaces/storages/control-flow-transformers/IControlFlowStorage'; import { IOptions } from '../../interfaces/options/IOptions'; import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator'; import { IVisitor } from '../../interfaces/node-transformers/IVisitor'; @@ -23,7 +24,6 @@ import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer'; import { FunctionControlFlowTransformer } from './FunctionControlFlowTransformer'; import { NodeGuards } from '../../node/NodeGuards'; -import { IControlFlowStorage } from '../../interfaces/storages/control-flow-transformers/IControlFlowStorage'; @injectable() export class StringArrayControlFlowTransformer extends FunctionControlFlowTransformer { @@ -120,12 +120,20 @@ export class StringArrayControlFlowTransformer extends FunctionControlFlowTransf && this.controlFlowStorageNodes.has(node); if (isControlFlowStorageNode) { - return estraverse.VisitorOption.Break; + return estraverse.VisitorOption.Skip; } return super.transformFunctionBodyNode(node, parentNode, functionNode, controlFlowStorage); } + /** + * @param {TNodeWithStatements} hostNode + * @returns {TControlFlowStorage} + */ + protected override getControlFlowStorage (hostNode: TNodeWithStatements): IControlFlowStorage { + return this.controlFlowStorageFactory(); + } + /** * @param {TNodeWithStatements} hostNode * @param {VariableDeclaration} controlFlowStorageNode diff --git a/src/node-transformers/rename-properties-transformers/replacer/RenamePropertiesReplacer.ts b/src/node-transformers/rename-properties-transformers/replacer/RenamePropertiesReplacer.ts index d5aac3cf..95cbd95d 100644 --- a/src/node-transformers/rename-properties-transformers/replacer/RenamePropertiesReplacer.ts +++ b/src/node-transformers/rename-properties-transformers/replacer/RenamePropertiesReplacer.ts @@ -12,7 +12,7 @@ import { IPropertyIdentifierNamesCacheStorage } from '../../../interfaces/storag import { IRenamePropertiesReplacer } from '../../../interfaces/node-transformers/rename-properties-transformers/replacer/IRenamePropertiesReplacer'; // eslint-disable-next-line import/no-internal-modules -import ReservedDomProperties from './ReservedDomProperties.json'; +import ReservedDomProperties from '../../../constants/ReservedDomProperties.json'; import { NodeGuards } from '../../../node/NodeGuards'; import { NodeFactory } from '../../../node/NodeFactory'; diff --git a/test/dev/dev.ts b/test/dev/dev.ts index 12c0c810..3495e2fa 100644 --- a/test/dev/dev.ts +++ b/test/dev/dev.ts @@ -1,26 +1,55 @@ 'use strict'; +import { StringArrayWrappersType } from '../../src/enums/node-transformers/string-array-transformers/StringArrayWrappersType'; + (function () { const JavaScriptObfuscator: any = require('../../index'); let obfuscatedCode: string = JavaScriptObfuscator.obfuscate( ` - async function xyzzy(a,b) - { - if (a) { - return await foo(a) ; - console.log(a) ; - } else { - return await bar(b) ; - console.log(b) ; + function foo () { + function bar() { + var string1 = 'string1'; + var string2 = 'string2'; + var string3 = 'string3'; + var string4 = 'string4'; + var string5 = 'string5'; + var string6 = 'string6'; + + function bark () { + var string1 = 'string1'; + var string2 = 'string2'; + var string3 = 'string3'; + var string4 = 'string4'; + var string5 = 'string5'; + var string6 = 'string6'; + } } + + bar() } + + console.log(foo()); `, { identifierNamesGenerator: 'mangled', compact: false, - simplify: true, - stringArray: false + controlFlowFlattening: false, + controlFlowFlatteningThreshold: 1, + simplify: false, + stringArrayRotate: false, + stringArray: true, + stringArrayIndexesType: [ + 'hexadecimal-number', + 'hexadecimal-numeric-string' + ], + stringArrayThreshold: 1, + stringArrayCallsTransform: true, + stringArrayCallsTransformThreshold: 1, + rotateStringArray: true, + stringArrayWrappersType: StringArrayWrappersType.Function, + transformObjectKeys: false, + seed: 1 } ).getObfuscatedCode(); diff --git a/test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/StringArrayControlFlowTransformer.spec.ts b/test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/StringArrayControlFlowTransformer.spec.ts index ab90c25e..4e65fa2e 100644 --- a/test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/StringArrayControlFlowTransformer.spec.ts +++ b/test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/StringArrayControlFlowTransformer.spec.ts @@ -191,6 +191,43 @@ describe('StringArrayControlFlowTransformer', function () { assert.match(obfuscatedCode, regexp); }); }); + + describe('Variant #5 - multiple `control flow storages` on the same block scope', () => { + const regexp: RegExp = new RegExp( + `var ${hexadecimalVariableMatch} *= *\\{` + + `${hexadecimalVariableMatch} *: *0x0, *` + + `${hexadecimalVariableMatch} *: *0x1 *` + + `\\}; *` + + `var ${hexadecimalVariableMatch} *= *\\{` + + + `${hexadecimalVariableMatch} *: *0x2, *` + + `${hexadecimalVariableMatch} *: *0x3 *` + + `\\};` + ); + + let obfuscatedCode: string; + + before(() => { + const code: string = readFileAsString(__dirname + '/fixtures/multiple-storages-1.js'); + + obfuscatedCode = JavaScriptObfuscator.obfuscate( + code, + { + ...NO_ADDITIONAL_NODES_PRESET, + stringArray: true, + stringArrayThreshold: 1, + stringArrayCallsTransform: true, + stringArrayCallsTransformThreshold: 1 + } + ).getObfuscatedCode(); + + console.log(obfuscatedCode); + }); + + it('should add `control flow storage` node with multiple items to the obfuscated code', () => { + assert.match(obfuscatedCode, regexp); + }); + }); }); describe('Variant #2 - negative cases', function () { @@ -320,7 +357,7 @@ describe('StringArrayControlFlowTransformer', function () { let obfuscatedCode: string; before(() => { - const code: string = readFileAsString(__dirname + '/fixtures/multiple-storages.js'); + const code: string = readFileAsString(__dirname + '/fixtures/multiple-storages-2.js'); obfuscatedCode = JavaScriptObfuscator.obfuscate( code, diff --git a/test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/fixtures/multiple-storages-1.js b/test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/fixtures/multiple-storages-1.js new file mode 100644 index 00000000..b55fa1e3 --- /dev/null +++ b/test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/fixtures/multiple-storages-1.js @@ -0,0 +1,7 @@ +(function () { + var variable1 = 'foo' + 'bar'; + + function foo (arg) { + var variable2 = 'baz' + 'bark'; + } +})(); diff --git a/test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/fixtures/multiple-storages.js b/test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/fixtures/multiple-storages-2.js similarity index 100% rename from test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/fixtures/multiple-storages.js rename to test/functional-tests/node-transformers/control-flow-transformers/string-array-control-flow-transformer/fixtures/multiple-storages-2.js diff --git a/test/unit-tests/generators/identifier-names-generators/MangledShuffledlIdentifierNamesGenerator.spec.ts b/test/unit-tests/generators/identifier-names-generators/MangledShuffledlIdentifierNamesGenerator.spec.ts index da739b3e..2e53bb9d 100644 --- a/test/unit-tests/generators/identifier-names-generators/MangledShuffledlIdentifierNamesGenerator.spec.ts +++ b/test/unit-tests/generators/identifier-names-generators/MangledShuffledlIdentifierNamesGenerator.spec.ts @@ -186,4 +186,33 @@ describe('MangledShuffledIdentifierNamesGenerator', () => { assert.isTrue(isSuccessComparison); }); }); + + describe('isValidIdentifierName', () => { + describe('Variant #1: reserved dom property name', () => { + let identifierNamesGenerator: IIdentifierNamesGenerator, + isValidName1: boolean, + isValidName2: boolean, + isValidName3: boolean; + + beforeEach(() => { + const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade(); + + inversifyContainerFacade.load('', '', {} ); + identifierNamesGenerator = inversifyContainerFacade.getNamed( + ServiceIdentifiers.IIdentifierNamesGenerator, + IdentifierNamesGenerator.MangledShuffledIdentifierNamesGenerator + ); + + isValidName1 = identifierNamesGenerator.isValidIdentifierName('Set'); + isValidName2 = identifierNamesGenerator.isValidIdentifierName('Array'); + isValidName3 = identifierNamesGenerator.isValidIdentifierName('WeakSet'); + }); + + it('should generate first identifier', () => { + assert.isFalse(isValidName1); + assert.isFalse(isValidName2); + assert.isTrue(isValidName3); + }); + }); + }); }); diff --git a/test/unit-tests/generators/identifier-names-generators/MangledlIdentifierNamesGenerator.spec.ts b/test/unit-tests/generators/identifier-names-generators/MangledlIdentifierNamesGenerator.spec.ts index ab536a44..8b812510 100644 --- a/test/unit-tests/generators/identifier-names-generators/MangledlIdentifierNamesGenerator.spec.ts +++ b/test/unit-tests/generators/identifier-names-generators/MangledlIdentifierNamesGenerator.spec.ts @@ -312,5 +312,32 @@ describe('MangledIdentifierNamesGenerator', () => { assert.equal(secondMangledIdentifierName, expectedSecondIdentifier); }); }); + + describe('Variant #3: reserved dom property name', () => { + let identifierNamesGenerator: IIdentifierNamesGenerator, + isValidName1: boolean, + isValidName2: boolean, + isValidName3: boolean; + + beforeEach(() => { + const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade(); + + inversifyContainerFacade.load('', '', {} ); + identifierNamesGenerator = inversifyContainerFacade.getNamed( + ServiceIdentifiers.IIdentifierNamesGenerator, + IdentifierNamesGenerator.MangledIdentifierNamesGenerator + ); + + isValidName1 = identifierNamesGenerator.isValidIdentifierName('Set'); + isValidName2 = identifierNamesGenerator.isValidIdentifierName('Array'); + isValidName3 = identifierNamesGenerator.isValidIdentifierName('WeakSet'); + }); + + it('should generate first identifier', () => { + assert.isFalse(isValidName1); + assert.isFalse(isValidName2); + assert.isTrue(isValidName3); + }); + }); }); });