Merge pull request #489 from javascript-obfuscator/method-definition-literal-key-fix

Added method-definition literal key converting to `computed`
This commit is contained in:
Timofey Kachalov
2020-01-09 17:33:03 +03:00
committed by GitHub
9 changed files with 184 additions and 62 deletions
+1
View File
@@ -3,6 +3,7 @@ Change Log
v0.22.0
---
* **Breaking:** auto-detection of kind of variables of inserted nodes, based on most prevailing kind of variables of source code
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/486
v0.21.1
---
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
@@ -17,6 +17,9 @@ import { NodeGuards } from '../../node/NodeGuards';
* replaces:
* foo () { //... };
*
* or
* 'foo' () { //... };
*
* on:
* ['foo'] { //... };
*
@@ -76,13 +79,52 @@ export class MethodDefinitionTransformer extends AbstractNodeTransformer {
* @returns {NodeGuards}
*/
public transformNode (methodDefinitionNode: ESTree.MethodDefinition, parentNode: ESTree.Node): ESTree.Node {
if (NodeGuards.isIdentifierNode(methodDefinitionNode.key)) {
return this.replaceIdentifierKey(methodDefinitionNode, methodDefinitionNode.key);
}
if (NodeGuards.isLiteralNode(methodDefinitionNode.key)) {
return this.replaceLiteralKey(methodDefinitionNode, methodDefinitionNode.key);
}
return methodDefinitionNode;
}
/**
* @param {MethodDefinition} methodDefinitionNode
* @param {Identifier} keyNode
* @returns {MethodDefinition}
*/
private replaceIdentifierKey (
methodDefinitionNode: ESTree.MethodDefinition,
keyNode: ESTree.Identifier
): ESTree.MethodDefinition {
if (
NodeGuards.isIdentifierNode(methodDefinitionNode.key) &&
!MethodDefinitionTransformer.ignoredNames.includes(methodDefinitionNode.key.name) &&
methodDefinitionNode.computed === false
!MethodDefinitionTransformer.ignoredNames.includes(keyNode.name)
&& !methodDefinitionNode.computed
) {
methodDefinitionNode.computed = true;
methodDefinitionNode.key = NodeFactory.literalNode(keyNode.name);
}
return methodDefinitionNode;
}
/**
* @param {MethodDefinition} methodDefinitionNode
* @param {Literal} keyNode
* @returns {MethodDefinition}
*/
private replaceLiteralKey (
methodDefinitionNode: ESTree.MethodDefinition,
keyNode: ESTree.Literal
): ESTree.MethodDefinition {
if (
typeof keyNode.value === 'string'
&& !MethodDefinitionTransformer.ignoredNames.includes(keyNode.value)
&& !methodDefinitionNode.computed
) {
methodDefinitionNode.computed = true;
methodDefinitionNode.key = NodeFactory.literalNode(methodDefinitionNode.key.name);
}
return methodDefinitionNode;
+3 -2
View File
@@ -7,8 +7,9 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
var foo = 'abcd'
var bar = 'abcde'
class Foo {
'bar'() {}
}
`,
{
...NO_ADDITIONAL_NODES_PRESET,
@@ -7,77 +7,151 @@ import { readFileAsString } from '../../../../helpers/readFileAsString';
import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscatorFacade';
describe('MethodDefinitionTransformer', () => {
describe('Variant #1: default behaviour', () => {
const regExp: RegExp = /\['bar'\]\(\)\{\}/;
describe('Variant #1: identifier key', () => {
describe('Variant #1: default behaviour', () => {
const regExp: RegExp = /\['bar'\]\(\)\{\}/;
let obfuscatedCode: string;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/sample-input.js');
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/identifier-key.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET
}
).getObfuscatedCode();
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET
}
).getObfuscatedCode();
});
it('should replace method definition node `key` property with square brackets literal', () => {
assert.match(obfuscatedCode, regExp);
});
});
it('should replace method definition node `key` property with square brackets literal', () => {
assert.match(obfuscatedCode, regExp);
describe('Variant #2: `stringArray` option is enabled', () => {
const stringArrayRegExp: RegExp = /var *_0x([a-f0-9]){4} *= *\['bar'\];/;
const stringArrayCallRegExp: RegExp = /\[_0x([a-f0-9]){4}\('0x0'\)\]\(\)\{\}/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/identifier-key.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1
}
).getObfuscatedCode();
});
it('should add method definition node `key` property to string array', () => {
assert.match(obfuscatedCode, stringArrayRegExp);
});
it('should replace method definition node `key` property with call to string array', () => {
assert.match(obfuscatedCode, stringArrayCallRegExp);
});
});
describe('Variant #3: `constructor` key', () => {
const regExp: RegExp = /constructor\(\)\{\}/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/identifier-key.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET
}
).getObfuscatedCode();
});
it('shouldn\'t transform method definition node with `constructor` key', () => {
assert.match(obfuscatedCode, regExp);
});
});
});
describe('Variant #2: `stringArray` option is enabled', () => {
const stringArrayRegExp: RegExp = /var *_0x([a-f0-9]){4} *= *\['bar'\];/;
const stringArrayCallRegExp: RegExp = /\[_0x([a-f0-9]){4}\('0x0'\)\]\(\)\{\}/;
describe('Variant #2: literal key', () => {
describe('Variant #1: Default behaviour', () => {
const regExp: RegExp = /\['bar'\]\(\)\{\}/;
let obfuscatedCode: string;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/sample-input.js');
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/literal-key.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1
}
).getObfuscatedCode();
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET
}
).getObfuscatedCode();
});
it('should replace method definition node `key` property with square brackets literal', () => {
assert.match(obfuscatedCode, regExp);
});
});
it('should add method definition node `key` property to string array', () => {
assert.match(obfuscatedCode, stringArrayRegExp);
describe('Variant #2: `stringArray` option is enabled', () => {
const stringArrayRegExp: RegExp = /var *_0x([a-f0-9]){4} *= *\['constructor', *'bar'];/;
const stringArrayCallRegExp: RegExp = /\[_0x([a-f0-9]){4}\('0x1'\)\]\(\)\{\}/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/literal-key.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1
}
).getObfuscatedCode();
});
it('should add method definition node `key` property to string array', () => {
assert.match(obfuscatedCode, stringArrayRegExp);
});
it('should replace method definition node `key` property with call to string array', () => {
assert.match(obfuscatedCode, stringArrayCallRegExp);
});
});
it('should replace method definition node `key` property with call to string array', () => {
assert.match(obfuscatedCode, stringArrayCallRegExp);
describe('Variant #3: `constructor` key', () => {
const regExp: RegExp = /'constructor'\(\)\{\}/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/literal-key.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET
}
).getObfuscatedCode();
});
it('shouldn\'t transform method definition node with `constructor` key', () => {
assert.match(obfuscatedCode, regExp);
});
});
});
describe('Variant #3: `constructor` key', () => {
const regExp: RegExp = /constructor\(\)\{\}/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/sample-input.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET
}
).getObfuscatedCode();
});
it('shouldn\'t transform method definition node with `constructor` key', () => {
assert.match(obfuscatedCode, regExp);
});
});
describe('Variant #4: async `get()` method', () => {
describe('Variant #3: async `get()` method', () => {
const classDeclarationRegExp: RegExp = /class *(_0x[a-f0-9]{4,6}) *{/;
const asyncMethodRegExp: RegExp = /static *async *\['get'] *\(\) *{}/;
@@ -0,0 +1,4 @@
class Foo {
'constructor' () {}
'bar' () {}
}