mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Fixed invalid code generation for start/middle rest arguments when controlFlowFlattenig option is enabled
Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/920
This commit is contained in:
@@ -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
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -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(
|
||||
|
||||
+12
-14
@@ -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();
|
||||
|
||||
|
||||
+70
-6
@@ -118,18 +118,18 @@ describe('CallExpressionControlFlowReplacer', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #4 - rest 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}\);/;
|
||||
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}, *\.\.\._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}\\);` +
|
||||
`'\\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-call-argument.js');
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/rest-as-start-call-argument.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
@@ -145,7 +145,71 @@ 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, 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}\\) *\\{` +
|
||||
`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-last-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 inside control flow storage node function', () => {
|
||||
assert.match(obfuscatedCode, controlFlowStorageNodeRegExp);
|
||||
});
|
||||
});
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
(function () {
|
||||
const log = console.log;
|
||||
const first = 'foo';
|
||||
const rest = ['bar', 'baz', 'bark'];
|
||||
const last = 'hawk';
|
||||
log(first, ...rest, last);
|
||||
})();
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
(function () {
|
||||
const log = console.log;
|
||||
const rest = ['foo', 'bar', 'baz'];
|
||||
const last = 'bark';
|
||||
log(...rest, last);
|
||||
})();
|
||||
Reference in New Issue
Block a user