Browse Source

fixed esprima crash when `unicodeEscapeSequence` is disabled

sanex3339 8 years ago
parent
commit
519ecbf084

+ 8 - 4
dist/index.js

@@ -801,11 +801,17 @@ var Utils = function () {
     }, {
     }, {
         key: "stringToUnicodeEscapeSequence",
         key: "stringToUnicodeEscapeSequence",
         value: function stringToUnicodeEscapeSequence(string) {
         value: function stringToUnicodeEscapeSequence(string) {
+            var nonLatinAndNonDigitsOnly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+
             var radix = 16;
             var radix = 16;
             var regexp = new RegExp('[\x00-\x7F]');
             var regexp = new RegExp('[\x00-\x7F]');
+            var escapeRegExp = new RegExp('[^a-zA-Z0-9]');
             var prefix = void 0,
             var prefix = void 0,
                 template = void 0;
                 template = void 0;
             return "" + string.replace(/[\s\S]/g, function (escape) {
             return "" + string.replace(/[\s\S]/g, function (escape) {
+                if (nonLatinAndNonDigitsOnly && !escapeRegExp.test(escape)) {
+                    return escape;
+                }
                 if (regexp.test(escape)) {
                 if (regexp.test(escape)) {
                     prefix = '\\x';
                     prefix = '\\x';
                     template = '0'.repeat(2);
                     template = '0'.repeat(2);
@@ -5755,7 +5761,7 @@ var StringLiteralReplacer = StringLiteralReplacer_1 = function (_AbstractReplace
             if (this.options.stringArray && replaceWithStringArrayFlag) {
             if (this.options.stringArray && replaceWithStringArrayFlag) {
                 return this.replaceStringLiteralWithStringArrayCall(nodeValue);
                 return this.replaceStringLiteralWithStringArrayCall(nodeValue);
             }
             }
-            return "'" + Utils_1.Utils.stringToUnicodeEscapeSequence(nodeValue) + "'";
+            return "'" + Utils_1.Utils.stringToUnicodeEscapeSequence(nodeValue, !this.options.unicodeEscapeSequence) + "'";
         }
         }
     }, {
     }, {
         key: "replaceStringLiteralWithStringArrayCall",
         key: "replaceStringLiteralWithStringArrayCall",
@@ -5770,9 +5776,7 @@ var StringLiteralReplacer = StringLiteralReplacer_1 = function (_AbstractReplace
                     value = CryptUtils_1.CryptUtils.btoa(value);
                     value = CryptUtils_1.CryptUtils.btoa(value);
                     break;
                     break;
             }
             }
-            if (this.options.unicodeEscapeSequence) {
-                value = Utils_1.Utils.stringToUnicodeEscapeSequence(value);
-            }
+            value = Utils_1.Utils.stringToUnicodeEscapeSequence(value, !this.options.unicodeEscapeSequence);
             var indexOfExistingValue = this.stringArrayStorage.getKeyOf(value);
             var indexOfExistingValue = this.stringArrayStorage.getKeyOf(value);
             var indexOfValue = void 0;
             var indexOfValue = void 0;
             if (indexOfExistingValue >= 0) {
             if (indexOfExistingValue >= 0) {

+ 2 - 4
src/node-transformers/node-obfuscators/replacers/StringLiteralReplacer.ts

@@ -65,7 +65,7 @@ export class StringLiteralReplacer extends AbstractReplacer {
             return this.replaceStringLiteralWithStringArrayCall(nodeValue);
             return this.replaceStringLiteralWithStringArrayCall(nodeValue);
         }
         }
 
 
-        return `'${Utils.stringToUnicodeEscapeSequence(nodeValue)}'`;
+        return `'${Utils.stringToUnicodeEscapeSequence(nodeValue, !this.options.unicodeEscapeSequence)}'`;
     }
     }
 
 
     /**
     /**
@@ -88,9 +88,7 @@ export class StringLiteralReplacer extends AbstractReplacer {
                 break;
                 break;
         }
         }
 
 
-        if (this.options.unicodeEscapeSequence) {
-            value = Utils.stringToUnicodeEscapeSequence(value);
-        }
+        value = Utils.stringToUnicodeEscapeSequence(value, !this.options.unicodeEscapeSequence);
 
 
         const indexOfExistingValue: number = <number>this.stringArrayStorage.getKeyOf(value);
         const indexOfExistingValue: number = <number>this.stringArrayStorage.getKeyOf(value);
 
 

+ 7 - 1
src/utils/Utils.ts

@@ -124,16 +124,22 @@ export class Utils {
 
 
     /**
     /**
      * @param string
      * @param string
+     * @param nonLatinAndNonDigitsOnly
      * @returns {string}
      * @returns {string}
      */
      */
-    public static stringToUnicodeEscapeSequence (string: string): string {
+    public static stringToUnicodeEscapeSequence (string: string, nonLatinAndNonDigitsOnly: boolean = false): string {
         const radix: number = 16;
         const radix: number = 16;
         const regexp: RegExp = new RegExp('[\x00-\x7F]');
         const regexp: RegExp = new RegExp('[\x00-\x7F]');
+        const escapeRegExp: RegExp = new RegExp('[^a-zA-Z0-9]');
 
 
         let prefix: string,
         let prefix: string,
             template: string;
             template: string;
 
 
         return `${string.replace(/[\s\S]/g, (escape: string): string => {
         return `${string.replace(/[\s\S]/g, (escape: string): string => {
+            if (nonLatinAndNonDigitsOnly && !escapeRegExp.test(escape)) {
+                return escape;
+            }
+            
             if (regexp.test(escape)) {
             if (regexp.test(escape)) {
                 prefix = '\\x';
                 prefix = '\\x';
                 template = '0'.repeat(2);
                 template = '0'.repeat(2);

+ 2 - 1
test/dev/dev.ts

@@ -84,7 +84,8 @@ if (!(<any>global)._babelPolyfill) {
         {
         {
             compact: false,
             compact: false,
             controlFlowFlattening: true,
             controlFlowFlattening: true,
-            disableConsoleOutput: false
+            disableConsoleOutput: false,
+            unicodeEscapeSequence: false
         }
         }
     ).getObfuscatedCode();
     ).getObfuscatedCode();
 
 

+ 1 - 0
test/fixtures/node-transformers/node-obfuscators/literal-obfuscator/literal-obfuscator-unicode-sequence.js

@@ -0,0 +1 @@
+var test = '\nreturn \n//# sourceURL= there can only be \'^\' and \'!\' markers in a subscription marble diagram.';

+ 29 - 0
test/functional-tests/node-transformers/node-obfuscators/LiteralObfuscator.spec.ts

@@ -4,6 +4,8 @@ import { IObfuscationResult } from '../../../../src/interfaces/IObfuscationResul
 
 
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 import { NO_CUSTOM_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 
 
+import { readFileAsString } from '../../../helpers/readFileAsString';
+
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscator';
 
 
 describe('LiteralObfuscator', () => {
 describe('LiteralObfuscator', () => {
@@ -54,6 +56,33 @@ describe('LiteralObfuscator', () => {
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-z0-9]){4}\('0x0'\);/);
             assert.match(obfuscationResult.getObfuscatedCode(),  /var *test *= *_0x([a-z0-9]){4}\('0x0'\);/);
         });
         });
 
 
+        it('should replace literal node value with raw value from unicode array if `unicodeEscapeSequence` and `stringArray` are disabled', () => {
+            let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                `var test = 'test';`,
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    unicodeEscapeSequence: false
+                }
+            );
+
+            assert.match(
+                obfuscationResult.getObfuscatedCode(),
+                /^var *test *= *'test';/
+            );
+        });
+
+        it('should\'t throw an error when string contains non-latin and non-digit characters and `unicodeEscapeSequence` is disabled', () => {
+            assert.doesNotThrow(() => JavaScriptObfuscator.obfuscate(
+                readFileAsString('./test/fixtures/node-transformers/node-obfuscators/literal-obfuscator/literal-obfuscator-unicode-sequence.js'),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    stringArray: true,
+                    stringArrayThreshold: 1,
+                    unicodeEscapeSequence: false
+                }
+            ));
+        });
+
         it('shouldn\'t replace short literal node value with unicode array value', () => {
         it('shouldn\'t replace short literal node value with unicode array value', () => {
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
             let obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 `var test = 'te';`,
                 `var test = 'te';`,

+ 8 - 3
test/unit-tests/utils/Utils.spec.ts

@@ -111,11 +111,16 @@ describe('Utils', () => {
         });
         });
     });
     });
 
 
-    describe('stringToUnicodeEscapeSequence (string: string): string', () => {
-        let expected: string = '\\x73\\x74\\x72\\x69\\x6e\\x67';
+    describe('stringToUnicodeEscapeSequence (string: string, nonLatinAndNonDigitsOnly: boolean = false): string', () => {
+        const expected1: string = '\\x73\\x74\\x72\\x69\\x6e\\x67';
+        const expected2: string = 'abc\\x21\\u0434\\u0435';
 
 
         it('should return a unicode escape sequence based on a given string', () => {
         it('should return a unicode escape sequence based on a given string', () => {
-            assert.equal(Utils.stringToUnicodeEscapeSequence('string'), expected);
+            assert.equal(Utils.stringToUnicodeEscapeSequence('string'), expected1);
+        });
+
+        it('should return a string where only non-digits and non-latin letters are escaped', () => {
+            assert.equal(Utils.stringToUnicodeEscapeSequence('abc!де', true), expected2);
         });
         });
     });
     });
 });
 });