From 1a27ecdad41ba0854a8a890774e1ec67c83ee427 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Thu, 19 May 2016 11:08:08 -0400 Subject: [PATCH] Override `child_process.execFile` asar patch for `child_process.exec` NodeJS implements `child_process.exec` by simply passing the whole command to `child_process.execFile`. See: - https://github.com/nodejs/node/blob/master/lib/child_process.js#L90 - https://github.com/nodejs/node/blob/master/lib/child_process.js#L99 Electron patches `child_process.execFile` to add support for `asar` archives by injecting logic that extracts the required files from the `asar` to a temporary location before delegating the work to the original `child_process.execFile`. In order to decide whether to inject the custom `asar` extracting logic, Electron makes use of a helper function called `splitPath()`. See: - https://github.com/electron/electron/blob/master/lib/common/asar.js#L37 If the first argument of the returned array equals `true`, means that the path is considered to be an `asar` archive, and thus the extraction logic takes place. The problem is that if the command passed to `child_process.execFile` *contains* a path to an asar archive, padded with other commands/arguments, `splitPath()` will consider it to be an `asar` archive, and will try to extract it, throwing a rightfully `Invalid package` error. Fixes: https://github.com/electron/electron/issues/5571 Signed-off-by: Juan Cruz Viotti --- lib/common/asar.js | 17 +++++++++++++++++ spec/asar-spec.js | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/lib/common/asar.js b/lib/common/asar.js index 262412813221..1d8474d1c563 100644 --- a/lib/common/asar.js +++ b/lib/common/asar.js @@ -589,6 +589,23 @@ return mkdirSync(p, mode) } } + + // Executing a command string containing a path to an asar + // archive confuses `child_process.execFile`, which is internally + // called by `child_process.{exec,execSync}`, causing + // Electron to consider the full command as a single path + // to an archive. + [ 'exec', 'execSync' ].forEach(function (functionName) { + var old = child_process[functionName] + child_process[functionName] = function () { + var processNoAsarOriginalValue = process.noAsar + process.noAsar = true + var result = old.apply(this, arguments) + process.noAsar = processNoAsarOriginalValue + return result + } + }) + overrideAPI(fs, 'open') overrideAPI(child_process, 'execFile') overrideAPISync(process, 'dlopen', 1) diff --git a/spec/asar-spec.js b/spec/asar-spec.js index f9c4e98ae8fa..ac0779d2f266 100644 --- a/spec/asar-spec.js +++ b/spec/asar-spec.js @@ -555,6 +555,30 @@ describe('asar package', function () { }) }) + describe('child_process.exec', function () { + var child_process = require('child_process'); + var echo = path.join(fixtures, 'asar', 'echo.asar', 'echo') + + it('should not try to extract the command if there is a reference to a file inside an .asar', function (done) { + child_process.exec('echo ' + echo + ' foo bar', function (error, stdout) { + assert.equal(error, null) + assert.equal(stdout.toString().replace(/\r/g, ''), echo + ' foo bar\n') + done() + }) + }) + }) + + describe('child_process.execSync', function () { + var child_process = require('child_process'); + var echo = path.join(fixtures, 'asar', 'echo.asar', 'echo') + + it('should not try to extract the command if there is a reference to a file inside an .asar', function (done) { + var stdout = child_process.execSync('echo ' + echo + ' foo bar') + assert.equal(stdout.toString().replace(/\r/g, ''), echo + ' foo bar\n') + done() + }) + }) + describe('child_process.execFile', function () { var echo, execFile, execFileSync, ref2 if (process.platform !== 'darwin') {