Skip to content

Bigint support #599

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 25, 2020
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
Change Log

v0.27.5
v0.28.0
---
* Added BigInt support. https://github.com/javascript-obfuscator/javascript-obfuscator/issues/588
* Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/554

v0.27.4
Expand Down
8 changes: 4 additions & 4 deletions 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.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "0.27.4",
"version": "0.28.0",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ export function StringArrayRotateFunctionTemplate (): string {
};

{code}
})({stringArrayName}, 0x{stringArrayRotationAmount});
})({stringArrayName}, {stringArrayRotationAmount});
`;
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ export class HexadecimalIdentifierNamesGenerator extends AbstractIdentifierNames
const rangeMaxInteger: number = 99_999_999;
const randomInteger: number = this.randomGenerator.getRandomInteger(rangeMinInteger, rangeMaxInteger);
const hexadecimalNumber: string = NumberUtils.toHex(randomInteger);
const prefixLength: number = Utils.hexadecimalPrefix.length + 1;
const baseNameLength: number = nameLength
? nameLength - prefixLength
: HexadecimalIdentifierNamesGenerator.baseIdentifierNameLength;
const prefixLength: number = Utils.hexadecimalPrefix.length;
const baseNameLength: number = (nameLength ?? HexadecimalIdentifierNamesGenerator.baseIdentifierNameLength)
+ prefixLength;
const baseIdentifierName: string = hexadecimalNumber.substr(0, baseNameLength);
const identifierName: string = `_${Utils.hexadecimalPrefix}${baseIdentifierName}`;
const identifierName: string = `_${baseIdentifierName}`;

if (!this.isValidIdentifierName(identifierName)) {
return this.generateNext(nameLength);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export class LiteralTransformer extends AbstractNodeTransformer {
break;

case 'number':
case 'bigint':
newLiteralNode = this.literalObfuscatingReplacerFactory(
LiteralObfuscatingReplacer.NumberLiteralObfuscatingReplacer
).replace(literalNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { IOptions } from '../../../../interfaces/options/IOptions';
import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
import { NodeFactory } from '../../../../node/NodeFactory';
import { NumberUtils } from '../../../../utils/NumberUtils';
import { Utils } from '../../../../utils/Utils';

@injectable()
export class NumberLiteralObfuscatingReplacer extends AbstractObfuscatingReplacer {
Expand All @@ -33,19 +32,19 @@ export class NumberLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
public replace (literalNode: ESTree.SimpleLiteral): ESTree.Node {
const literalValue: ESTree.SimpleLiteral['value'] = literalNode.value;

if (typeof literalValue !== 'number') {
throw new Error('`NumberLiteralObfuscatingReplacer` should accept only literals with `number` value');
if (typeof literalValue !== 'number' && typeof literalValue !== 'bigint') {
throw new Error('`NumberLiteralObfuscatingReplacer` should accept only literals with `number` and `bigint` value');
}

let rawValue: string;

if (this.numberLiteralCache.has(literalValue)) {
rawValue = <string>this.numberLiteralCache.get(literalValue);
} else {
if (!NumberUtils.isCeil(literalValue)) {
rawValue = String(literalValue);
if (NumberUtils.isCeil(literalValue)) {
rawValue = NumberUtils.toHex(literalValue);
} else {
rawValue = `${Utils.hexadecimalPrefix}${NumberUtils.toHex(literalValue)}`;
rawValue = String(literalValue);
}

this.numberLiteralCache.set(literalValue, rawValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
import { NodeMetadata } from '../../../../node/NodeMetadata';
import { NodeFactory } from '../../../../node/NodeFactory';
import { NumberUtils } from '../../../../utils/NumberUtils';
import { Utils } from '../../../../utils/Utils';

@injectable()
export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplacer implements IInitializable {
Expand Down Expand Up @@ -129,7 +128,7 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
private replaceWithStringArrayCallNode (stringArrayStorageItemData: IStringArrayStorageItemData): ESTree.Node {
const { index, decodeKey } = stringArrayStorageItemData;

const hexadecimalIndex: string = `${Utils.hexadecimalPrefix}${NumberUtils.toHex(index)}`;
const hexadecimalIndex: string = NumberUtils.toHex(index);
const callExpressionArgs: (ESTree.Expression | ESTree.SpreadElement)[] = [
StringLiteralObfuscatingReplacer.getHexadecimalLiteralNode(hexadecimalIndex)
];
Expand Down
2 changes: 1 addition & 1 deletion src/storages/string-array/StringArrayStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
/**
* @type {number}
*/
private static readonly stringArrayNameLength: number = 7;
private static readonly stringArrayNameLength: number = 4;

/**
* @type {IArrayUtils}
Expand Down
18 changes: 13 additions & 5 deletions src/utils/NumberUtils.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { Utils } from './Utils';

export class NumberUtils {
/**
* @param {number} dec
* @param {number} number
* @returns {string}
*/
public static toHex (dec: number): string {
public static toHex (number: number | bigint): string {
const radix: number = 16;

return dec.toString(radix);
const basePart: string = typeof number === 'number'
? number.toString(radix)
: `${number.toString(radix)}n`;

return `${Utils.hexadecimalPrefix}${basePart}`;
}

/**
* @param {number} number
* @returns {boolean}
*/
public static isCeil (number: number): boolean {
return number % 1 === 0;
public static isCeil (number: number | bigint): boolean {
return typeof number === 'number'
? number % 1 === 0
: true;
}
}
8 changes: 4 additions & 4 deletions test/dev/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo

let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
var a, b;
({a, ...b} = {a: 1, b: 2, c: 3});
var foo = 'abc';
`,
{
...NO_ADDITIONAL_NODES_PRESET,
compact: false,
renameGlobals: true
renameGlobals: true,
stringArray: true,
stringArrayThreshold: 1
}
).getObfuscatedCode();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,27 @@ describe('JavaScriptObfuscator', () => {
});
});

describe('BigInt support', () => {
const regExp: RegExp = /return 0x20000000000001n *\+ *0xan *\+ *0xan;/;

let obfuscatedCode: string;

beforeEach(() => {
const code: string = readFileAsString(__dirname + '/fixtures/bigint-support.js');

obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET
}
).getObfuscatedCode();
});

it('should support BigInt', () => {
assert.match(obfuscatedCode, regExp);
});
});

describe('mangled identifier names generator', () => {
const regExp: RegExp = /var c *= *0x1/;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function test() {
return 9007199254740993n + 10n + 0xan;
}
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,29 @@ describe('LiteralTransformer', () => {
});
});

describe('transformation of literal node with bigint value', () => {
const regExp: RegExp = /^var test *= *0xan;$/;

let obfuscatedCode: string;

before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/bigint-value.js');

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

it('should transform literal node', () => {
assert.match(obfuscatedCode, regExp);
});
});

describe('RegExp literal', () => {
const regExp: RegExp = /^var regExp *= *\/\(\\d\+\)\/;$/;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var test = 10n;
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,51 @@ import { InversifyContainerFacade } from '../../../../src/container/InversifyCon

describe('HexadecimalIdentifierNamesGenerator', () => {
describe('generateNext', () => {
let identifierNamesGenerator: IIdentifierNamesGenerator,
hexadecimalIdentifierName: string,
regExp: RegExp;
describe('Base', () => {
let identifierNamesGenerator: IIdentifierNamesGenerator,
hexadecimalIdentifierName: string,
regExp: RegExp;

before(() => {
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();

inversifyContainerFacade.load('', '', {});
identifierNamesGenerator = inversifyContainerFacade.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator
);

hexadecimalIdentifierName = identifierNamesGenerator.generateNext();
regExp = /^_0x(\w){4,6}$/;
});

before(() => {
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
it('should return hexadecimal name', () => {
assert.match(hexadecimalIdentifierName, regExp);
})
});

inversifyContainerFacade.load('', '', {});
identifierNamesGenerator = inversifyContainerFacade.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator
);
describe('Custom length', () => {
let identifierNamesGenerator: IIdentifierNamesGenerator,
hexadecimalIdentifierName: string,
regExp: RegExp;

hexadecimalIdentifierName = identifierNamesGenerator.generateNext();
regExp = /^_0x(\w){4,6}$/;
});
before(() => {
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();

it('should return hexadecimal name', () => {
assert.match(hexadecimalIdentifierName, regExp);
})
inversifyContainerFacade.load('', '', {});
identifierNamesGenerator = inversifyContainerFacade.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator
);

hexadecimalIdentifierName = identifierNamesGenerator.generateNext(3);
regExp = /^_0x(\w){3}$/;
});

it('should return hexadecimal name', () => {
assert.match(hexadecimalIdentifierName, regExp);
})
});
});

describe('generateForGlobalScope', () => {
Expand Down
40 changes: 36 additions & 4 deletions test/unit-tests/utils/NumberUtils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('NumberUtils', () => {
describe('toHex', () => {
describe('Variant #1: number `0`', () => {
const number: number = 0;
const expectedHexString = '0';
const expectedHexString = '0x0';

let hexString: string;

Expand All @@ -21,7 +21,7 @@ describe('NumberUtils', () => {

describe('Variant #2: number `10`', () => {
const number: number = 10;
const expectedHexString = 'a';
const expectedHexString = '0xa';

let hexString: string;

Expand All @@ -36,7 +36,7 @@ describe('NumberUtils', () => {

describe('Variant #3: number `17`', () => {
const number: number = 17;
const expectedHexString = '11';
const expectedHexString = '0x11';

let hexString: string;

Expand All @@ -51,7 +51,7 @@ describe('NumberUtils', () => {

describe('Variant #4: number `536870912`', () => {
const number: number = 536870912;
const expectedHexString = '20000000';
const expectedHexString = '0x20000000';

let hexString: string;

Expand All @@ -63,6 +63,22 @@ describe('NumberUtils', () => {
assert.equal(hexString, expectedHexString);
});
});

describe('Variant #5: bigint number `10n`', () => {
// @ts-ignore
const number: bigint = 10n;
const expectedHexString = '0xan';

let hexString: string;

before(() => {
hexString = NumberUtils.toHex(number);
});

it('should create a string with hexadecimal value from a given bigint number', () => {
assert.equal(hexString, expectedHexString);
});
});
});

describe('isCeil', () => {
Expand Down Expand Up @@ -95,5 +111,21 @@ describe('NumberUtils', () => {
assert.equal(result, expectedResult);
});
});

describe('bigint number', () => {
// @ts-ignore
const number: bigint = 10n;
const expectedResult: boolean = true;

let result: boolean;

before(() => {
result = NumberUtils.isCeil(number);
});

it('should return true', () => {
assert.equal(result, expectedResult);
});
});
});
});