Skip to content
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

Misleading Exception #760

Closed
fqmoon opened this issue Sep 24, 2020 · 17 comments
Closed

Misleading Exception #760

fqmoon opened this issue Sep 24, 2020 · 17 comments

Comments

@fqmoon
Copy link

fqmoon commented Sep 24, 2020

When I want to obfuscate one directory like this:
javascript-obfuscator <srcDir> --output <destDir> --config <myConfig>
If in my config I assign value to sourceMapFileName , then an exception thown:

----- now run cmd: 'javascript-obfuscator dist\dev-bundle       --output dist\prod-bundle       --config buildScripts\obfuscate.config.json' -----
Error: EPERM: operation not permitted, mkdir 'D:\'
    at Object.mkdirSync (fs.js:947:3)
    at mkdirpNativeSync (D:\workspace\HiEarthSdk\node_modules\mkdirp\lib\mkdirp-native.js:25:17)
    at Object.sync (D:\workspace\HiEarthSdk\node_modules\mkdirp\index.js:21:7)
    at t.ObfuscatedCodeWriter.writeFile (D:\workspace\HiEarthSdk\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\cli\utils\ObfuscatedCodeWriter.ts:82:16)
    at j.apply (D:\workspace\HiEarthSdk\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\cli\JavaScriptObfuscatorCLI.ts:195:39)
    at j.processSourceCodeWithSourceMap (D:\workspace\HiEarthSdk\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\decorators\Initializable.ts:61:39)
    at j.apply (D:\workspace\HiEarthSdk\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\cli\JavaScriptObfuscatorCLI.ts:178:18)
    at j.processSourceCode (D:\workspace\HiEarthSdk\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\decorators\Initializable.ts:61:39)
    at D:\workspace\HiEarthSdk\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\cli\JavaScriptObfuscatorCLI.ts:165:22
    at Array.forEach (<anonymous>)
(node:6204) UnhandledPromiseRejectionWarning: Error: Command failed: javascript-obfuscator dist\dev-bundle       --output dist\prod-bundle       --config buildScripts\obfuscate.config.jso
n

The exception is too terrible and I found out reason after one day...

Expected Behavior

So when obfuscating one directory the option sourceMapFileName should not be set?
If set I want get correct prompt... Thanks!

Your Environment

  • Obfuscator version used: windows10
  • Node version used: v14.10.0
@sanex3339
Copy link
Member

@fqmoon
Copy link
Author

fqmoon commented Sep 25, 2020

No, I think the root reason is OUTPUT PATH IS WRONG
You can:

  1. In the config file:
    set any value to option sourceMapFileName
    set true to option sourceMap
  2. obfuscate a directory: javascript-obfuscator <srcDir> --output <distDir> --config <yourConfigFile>

So I can get the exception say Error: EPERM: operation not permitted, mkdir 'D:\'
Of course you can't make a dir named "D:\" but the app want to

Reproduce Repos

I create a reproduce repos: https://github.com/njw6622/test-obfuscator.git
You can clone it for test
test cmds:

git clone https://github.com/njw6622/test-obfuscator.git
cd test-obfuscator
npm i
npm test

@sanex3339
Copy link
Member

sanex3339 commented Sep 25, 2020

Ok. But the problem is that i can't test it, because i'm developing under UNIX environment (

@da411d
Copy link
Contributor

da411d commented Sep 25, 2020

Yes, i managed to reproduce the problem.
Will investigate tonight.

@sanex3339
Copy link
Member

sanex3339 commented Sep 25, 2020

Thank you.
The main problem, i'm not sure how to properly test cross-platform code. I mean, I can test it with the Travis CI, but I want to emulate windows behaviour locally too under Unix.

@da411d
Copy link
Contributor

da411d commented Sep 25, 2020

First, I added some console.log to mkdirp and javascript-obfuscator.
On the left is displayed current configuration, on the right - test proccess.
We can see that this problem is not caused by saving obfuscated file, this is problem with saving source map file.
image

Code from screenshot config.json
{
    "optionsPreset": "default",
    "sourceMap": true,
    "sourceMapFileName": "abcdefg"
}

Console output

writeFile: "dist\src\a.js" obfuscatedCode.getObfuscatedCode()
mkdirpSync: dist\src undefined
writeFile: "/abcdefg.js.map" obfuscatedCode.getSourceMap()
mkdirpSync: / undefined

[javascript-obfuscator-cli] Error in file: src\a.js...
Error: EPERM: operation not permitted, mkdir 'D:\'
    at Object.mkdirSync (fs.js:840:3)
    at mkdirpNativeSync (D:\_PROJECTS\_WEB\test2\test-obfuscator\node_modules\mkdirp\lib\mkdirp-native.js:26:17)
    at Object.this (D:\_PROJECTS\_WEB\test2\test-obfuscator\node_modules\mkdirp\index.js:22:7)
    at t.ObfuscatedCodeWriter.ObfuscatedCodeWriter [as writeFile] (D:\_PROJECTS\_WEB\test2\test-obfuscator\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\cli\utils\SourceCodeReader.ts:21:32)
    at F.apply (D:\_PROJECTS\_WEB\test2\test-obfuscator\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\cli\JavaScriptObfuscatorCLI.ts:226:74)
    at F.obfuscatedCodeWriter (D:\_PROJECTS\_WEB\test2\test-obfuscator\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\decorators\Initializable.ts:61:39)
    at F.apply (D:\_PROJECTS\_WEB\test2\test-obfuscator\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\cli\JavaScriptObfuscatorCLI.ts:197:14)
    at F.value (D:\_PROJECTS\_WEB\test2\test-obfuscator\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\decorators\Initializable.ts:61:39)
    at D:\_PROJECTS\_WEB\test2\test-obfuscator\node_modules\javascript-obfuscator\dist\webpack:\JavaScriptObfuscator\src\cli\JavaScriptObfuscatorCLI.ts:188:5
    at Array.forEach ()
npm ERR! Test failed.  See above for more details.

The exception is caused by mkdirp when it attempts to create folder "/".
image

Code from screenshot test.js
const mkdirp = require("mkdirp");
mkdirp.sync("/")

Console output

internal/fs/utils.js:230
    throw err;
    ^

Error: EPERM: operation not permitted, mkdir 'D:\'
�[90m    at Object.mkdirSync (fs.js:840:3)�[39m
    at mkdirpNativeSync (D:\_PROJECTS\_WEB\test2\test\node_modules\�[4mmkdirp�[24m\lib\mkdirp-native.js:25:17)
    at Function.mkdirpSync [as sync] (D:\_PROJECTS\_WEB\test2\test\node_modules\�[4mmkdirp�[24m\index.js:21:7)
    at Object. (D:\_PROJECTS\_WEB\test2\test\test.js:2:8)
�[90m    at Module._compile (internal/modules/cjs/loader.js:1158:30)�[39m
�[90m    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)�[39m
�[90m    at Module.load (internal/modules/cjs/loader.js:1002:32)�[39m
�[90m    at Function.Module._load (internal/modules/cjs/loader.js:901:14)�[39m
�[90m    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)�[39m
�[90m    at internal/main/run_main_module.js:18:47�[39m {
  errno: �[33m-4048�[39m,
  syscall: �[32m'mkdir'�[39m,
  code: �[32m'EPERM'�[39m,
  path: �[32m'D:\\'�[39m
}

The problem is that function getOutputSourceMapPath is generating strange paths.
I copied function to separate file and did some random tests.
First example is for our case. The second and last also look the most strange for me.
image

Code from screenshot test_codeWriter__getOutputSourceMapPath.js
const getOutputSourceMapPath = (outputCodePath, sourceMapFileName = '') => {
  if (sourceMapFileName) {
    outputCodePath = `${outputCodePath.substring(
        0, outputCodePath.lastIndexOf('/')
    )}/${sourceMapFileName}`;
  }

if (!/.js.map$/.test(outputCodePath)) {
outputCodePath = ${outputCodePath.split(".")[0]}.js.map;
} else if (/.js$/.test(outputCodePath)) {
outputCodePath += '.map';
}

return outputCodePath;
}

const tests = [
["", "abcdefg"],
["./", "./abcdefg"],
["", "./abcdefg"],
["", "./abcdefg"],

["path.with/dot.in.name/", "abcdefg"],
["pathwith/dot.in.name/", "abcdefg"],
["dir/dist", "abcdefg.some.suffix.maybe"],
["path.with/dot.in.name/", "abcdefg.some.suffix.maybe"],

["/dir/dist", "abcdefg"],
["/dir", "abcdefg"],
["dir/dist", "abcdefg"],
["dir", "abcdefg"],

["D:/dir/dist", "abcdefg"],
["D:/dir/dist", "../abcdefg"],
];

tests.forEach(args => {
const result = getOutputSourceMapPath(...args);
console.log(\ngetOutputSourceMapPath(${args.map(a => "${a}").join(", ")}) = ${result});
});

Console output

getOutputSourceMapPath("", "abcdefg") = /abcdefg.js.map

getOutputSourceMapPath("./", "./abcdefg") = .js.map

getOutputSourceMapPath("", "./abcdefg") = /.js.map

getOutputSourceMapPath("", "./abcdefg") = /.js.map

getOutputSourceMapPath("path.with/dot.in.name/", "abcdefg") = path.js.map

getOutputSourceMapPath("pathwith/dot.in.name/", "abcdefg") = pathwith/dot.js.map

getOutputSourceMapPath("dir/dist", "abcdefg.some.suffix.maybe") = dir/abcdefg.js.map

getOutputSourceMapPath("path.with/dot.in.name/", "abcdefg.some.suffix.maybe") = path.js.map

getOutputSourceMapPath("/dir/dist", "abcdefg") = /dir/abcdefg.js.map

getOutputSourceMapPath("/dir", "abcdefg") = /abcdefg.js.map

getOutputSourceMapPath("dir/dist", "abcdefg") = dir/abcdefg.js.map

getOutputSourceMapPath("dir", "abcdefg") = /abcdefg.js.map

getOutputSourceMapPath("D:/dir/dist", "abcdefg") = D:/dir/abcdefg.js.map

getOutputSourceMapPath("D:/dir/dist", "../abcdefg") = D:/dir/.js.map

Also i remember that getOutputCodePath also had problems on Windows #576

So I think that working with paths needs refactoring and more tests, but I don't know good ways to do it. Maybe path.resolve is better for this? Also it may exclude bugs with splitting by ".".

@hecht-software
Copy link

Same here on Windows even with one file instead of whole directory. My workaround is to specify a full path for the source map file. I guess this doesn't work for directories.

I remember that I had a problem creating nested directories on Windows and Linux a few years ago. I didn't look into the problem in detail, but I leave you this code which is still in use and maybe helpul here if it's the same issue. It works like mkdir -p but takes Windows traits into account:

icl.pathDelimRegex = /[\/\\]/;

icl.getDirPathByFilePath = function(path)
{
   var pathEntities = path.split(icl.pathDelimRegex);
   pathEntities.pop();
   return pathEntities.join("/");
};

icl.createDirDone = function(dir, fprops)
{
   if (fprops === undefined)
   {
      fprops = 0o777;
   }

   var d = icl.Deferred();

   function createDirRcsv(dirEntities, i)
   {
      var curDir = dirEntities.slice(0, i).join("/");
      fs.mkdir(curDir, fprops, function(err) {
         if (err && err.code !== "EEXIST")
         {
            d.reject(err);
         }
         else if (i <= dirEntities.length)
         {
            createDirRcsv(dirEntities, i+1);
         }
         else
         {
            d.resolve();
         }
      });
   }

   var dirEntities = dir.split(icl.pathDelimRegex);
   var i = 1;
   if (/^[\\\/]{2}/.test(dir))
   {
      i = 3;
   }
   else if (!dirEntities[0].length || dirEntities[0][dirEntities[0].length - 1] === ":")
   {
      // absolute path beginning with "/" (Linux etc.) or "X:" (Windows)
      i = 2;
   }
   createDirRcsv(dirEntities, i);

   return d.promise();
};

// Then it's used like that:
icl.createDirDone(icl.getDirPathByFilePath(path)).then(/*...*/);

@sanex3339
Copy link
Member

I managed to setup TravisCI build under windows.
https://travis-ci.com/github/javascript-obfuscator/javascript-obfuscator/jobs/395863667

It fails with the same error. So, now i'll try to fix it

@sanex3339
Copy link
Member

Anybody can test this PR:
#772 ?

@sanex3339 sanex3339 reopened this Oct 8, 2020
@sanex3339
Copy link
Member

Merged to the master branch. I'll release a new version soon.

@fishbone1
Copy link

Thank you!
I couldn't test it yesterday. Did someone else test it?

@sanex3339
Copy link
Member

sanex3339 commented Oct 8, 2020

You can test it right now directly from master branch. I'll plan to release the next version only in 10 hours.

@sanex3339
Copy link
Member

sanex3339 commented Oct 8, 2020

Have anybody tested this?

@fishbone1
Copy link

Sorry, I need more time, I think I'm ready in a few hours

@fishbone1
Copy link

I tested it and it works with master. I also reproduced the error from last week with the old version before, to make sure I can trust the positive result. Thanks for fixing it!

@sanex3339
Copy link
Member

Nice! I'll release the new version soon.

@sanex3339
Copy link
Member

Released as 2.5.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants