Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Change Log

v2.13.0
---
* Fixed invalid code generation for start/middle rest arguments when `controlFlowFlattenig` option is enabled. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/920
* **Internal**: Added support of `node@16` and dropped support of `node@10`. This should not affect obfuscated code

v2.12.0
Expand Down
2 changes: 1 addition & 1 deletion dist/index.browser.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.cli.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,18 @@ export class CallExpressionFunctionNode extends AbstractCustomNode {

const baseIdentifierNode: ESTree.Identifier = NodeFactory.identifierNode(`param${i + 1}`);

params.push(
isSpreadCallArgument
? NodeFactory.restElementNode(baseIdentifierNode)
: baseIdentifierNode
);
callArguments.push(
isSpreadCallArgument
? NodeFactory.spreadElementNode(baseIdentifierNode)
: baseIdentifierNode
);
if (isSpreadCallArgument) {
params.push(NodeFactory.restElementNode(baseIdentifierNode));
callArguments.push(NodeFactory.spreadElementNode(baseIdentifierNode));

const isMiddleSpreadCallArgument: boolean = i < argumentsLength - 1;
if (isMiddleSpreadCallArgument) {
break;
}
} else {
params.push(baseIdentifierNode);
callArguments.push(baseIdentifierNode);
}
}

const structure: TStatement = NodeFactory.expressionStatementNode(
Expand Down
26 changes: 12 additions & 14 deletions test/dev/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,22 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo

let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
var variable1 = '5' - 3;
var variable2 = '5' + 3;
var variable3 = '5' + - '2';
var variable4 = ['10','10','10','10','10'].map(parseInt);
var variable5 = 'foo ' + 1 + 1;
console.log(variable1);
console.log(variable2);
console.log(variable3);
console.log(variable4);
console.log(variable5);
function foo(a, b, c, d) {
console.log(a, b, c, d)
}

function bar(...args) {
foo(...args, 5)
}

bar(...[1, 2, 3], 4)
`,
{
...NO_ADDITIONAL_NODES_PRESET,
compact: false,
stringArray: true,
stringArrayThreshold: 1,
rotateStringArray: true,
stringArrayWrappersCount: 3
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
identifierNamesGenerator: 'mangled'
}
).getObfuscatedCode();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,71 @@ describe('CallExpressionControlFlowReplacer', function () {
});
});

describe('Variant #4 - rest call argument', () => {
describe('Variant #4 - rest as start call argument', () => {
const controlFlowStorageCallRegExp: RegExp = /_0x([a-f0-9]){4,6}\['\w{5}']\(_0x([a-f0-9]){4,6}, *\.\.\._0x([a-f0-9]){4,6}, *_0x([a-f0-9]){4,6}\);/;
const controlFlowStorageNodeRegExp: RegExp = new RegExp(`` +
`'\\w{5}' *: *function *\\(_0x([a-f0-9]){4,6}, *\.\.\._0x([a-f0-9]){4,6}\\) *\\{` +
`return *_0x([a-f0-9]){4,6}\\(\.\.\._0x([a-f0-9]){4,6}\\);` +
`\\}` +
``);

let obfuscatedCode: string;

before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/rest-as-start-call-argument.js');

obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1
}
).getObfuscatedCode();
});

it('should replace call expression node with call to control flow storage node', () => {
assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
});

it('should keep rest parameter and rest call argument, but remove all function parameters after rest parameter', () => {
assert.match(obfuscatedCode, controlFlowStorageNodeRegExp);
});
});

describe('Variant #5 - rest as middle call argument', () => {
const controlFlowStorageCallRegExp: RegExp = /_0x([a-f0-9]){4,6}\['\w{5}']\(_0x([a-f0-9]){4,6}, *_0x([a-f0-9]){4,6}, *\.\.\._0x([a-f0-9]){4,6}, *_0x([a-f0-9]){4,6}\);/;
const controlFlowStorageNodeRegExp: RegExp = new RegExp(`` +
`'\\w{5}' *: *function *\\(_0x([a-f0-9]){4,6}, *_0x([a-f0-9]){4,6}, *\.\.\._0x([a-f0-9]){4,6}\\) *\\{` +
`return *_0x([a-f0-9]){4,6}\\(_0x([a-f0-9]){4,6}, *\.\.\._0x([a-f0-9]){4,6}\\);` +
`\\}` +
``);

let obfuscatedCode: string;

before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/rest-as-middle-call-argument.js');

obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1
}
).getObfuscatedCode();
});

it('should replace call expression node with call to control flow storage node', () => {
assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
});

it('should keep rest parameter and rest call argument, but remove all function parameters after rest parameter', () => {
assert.match(obfuscatedCode, controlFlowStorageNodeRegExp);
});
});

describe('Variant #6 - rest as last call argument', () => {
const controlFlowStorageCallRegExp: RegExp = /_0x([a-f0-9]){4,6}\['\w{5}']\(_0x([a-f0-9]){4,6}, *_0x([a-f0-9]){4,6}, *\.\.\._0x([a-f0-9]){4,6}\);/;
const controlFlowStorageNodeRegExp: RegExp = new RegExp(`` +
`'\\w{5}' *: *function *\\(_0x([a-f0-9]){4,6}, *_0x([a-f0-9]){4,6}, *\.\.\._0x([a-f0-9]){4,6}\\) *\\{` +
Expand All @@ -129,7 +193,7 @@ describe('CallExpressionControlFlowReplacer', function () {
let obfuscatedCode: string;

before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/rest-call-argument.js');
const code: string = readFileAsString(__dirname + '/fixtures/rest-as-last-call-argument.js');

obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
Expand All @@ -145,7 +209,7 @@ describe('CallExpressionControlFlowReplacer', function () {
assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
});

it('should keep spread parameter and rest call argument inside control flow storage node function', () => {
it('should keep rest parameter and rest call argument inside control flow storage node function', () => {
assert.match(obfuscatedCode, controlFlowStorageNodeRegExp);
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(function () {
const log = console.log;
const first = 'foo';
const rest = ['bar', 'baz', 'bark'];
const last = 'hawk';
log(first, ...rest, last);
})();
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(function () {
const log = console.log;
const rest = ['foo', 'bar', 'baz'];
const last = 'bark';
log(...rest, last);
})();