Skip to content

Commit

Permalink
fix: improper wrapping of fs.promises.readFile (#29577)
Browse files Browse the repository at this point in the history
  • Loading branch information
trop[bot] committed Jun 8, 2021
1 parent 73696ea commit e3a613d
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 45 deletions.
110 changes: 65 additions & 45 deletions lib/asar/fs-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,63 +490,83 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
}
};

const { readFile } = fs;
fs.readFile = function (pathArgument: string, options: any, callback: any) {
function fsReadFileAsar (pathArgument: string, options: any, callback: any) {
const pathInfo = splitPath(pathArgument);
if (!pathInfo.isAsar) return readFile.apply(this, arguments);
const { asarPath, filePath } = pathInfo;
if (pathInfo.isAsar) {
const { asarPath, filePath } = pathInfo;

if (typeof options === 'function') {
callback = options;
options = { encoding: null };
} else if (typeof options === 'string') {
options = { encoding: options };
} else if (options === null || options === undefined) {
options = { encoding: null };
} else if (typeof options !== 'object') {
throw new TypeError('Bad arguments');
}
if (typeof options === 'function') {
callback = options;
options = { encoding: null };
} else if (typeof options === 'string') {
options = { encoding: options };
} else if (options === null || options === undefined) {
options = { encoding: null };
} else if (typeof options !== 'object') {
throw new TypeError('Bad arguments');
}

const { encoding } = options;
const archive = getOrCreateArchive(asarPath);
if (!archive) {
const error = createError(AsarError.INVALID_ARCHIVE, { asarPath });
nextTick(callback, [error]);
return;
}
const { encoding } = options;
const archive = getOrCreateArchive(asarPath);
if (!archive) {
const error = createError(AsarError.INVALID_ARCHIVE, { asarPath });
nextTick(callback, [error]);
return;
}

const info = archive.getFileInfo(filePath);
if (!info) {
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath });
nextTick(callback, [error]);
return;
}
const info = archive.getFileInfo(filePath);
if (!info) {
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath });
nextTick(callback, [error]);
return;
}

if (info.size === 0) {
nextTick(callback, [null, encoding ? '' : Buffer.alloc(0)]);
return;
}
if (info.size === 0) {
nextTick(callback, [null, encoding ? '' : Buffer.alloc(0)]);
return;
}

if (info.unpacked) {
const realPath = archive.copyFileOut(filePath);
return fs.readFile(realPath, options, callback);
if (info.unpacked) {
const realPath = archive.copyFileOut(filePath);
return fs.readFile(realPath, options, callback);
}

const buffer = Buffer.alloc(info.size);
const fd = archive.getFd();
if (!(fd >= 0)) {
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath });
nextTick(callback, [error]);
return;
}

logASARAccess(asarPath, filePath, info.offset);
fs.read(fd, buffer, 0, info.size, info.offset, (error: Error) => {
callback(error, encoding ? buffer.toString(encoding) : buffer);
});
}
}

const buffer = Buffer.alloc(info.size);
const fd = archive.getFd();
if (!(fd >= 0)) {
const error = createError(AsarError.NOT_FOUND, { asarPath, filePath });
nextTick(callback, [error]);
return;
const { readFile } = fs;
fs.readFile = function (pathArgument: string, options: any, callback: any) {
const pathInfo = splitPath(pathArgument);
if (!pathInfo.isAsar) {
return readFile.apply(this, arguments);
}

logASARAccess(asarPath, filePath, info.offset);
fs.read(fd, buffer, 0, info.size, info.offset, (error: Error) => {
callback(error, encoding ? buffer.toString(encoding) : buffer);
});
return fsReadFileAsar(pathArgument, options, callback);
};

fs.promises.readFile = util.promisify(fs.readFile);
const { readFile: readFilePromise } = fs.promises;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
fs.promises.readFile = function (pathArgument: string, options: any) {
const pathInfo = splitPath(pathArgument);
if (!pathInfo.isAsar) {
return readFilePromise.apply(this, arguments);
}

const p = util.promisify(fsReadFileAsar);
return p(pathArgument, options);
};

const { readFileSync } = fs;
fs.readFileSync = function (pathArgument: string, options: any) {
Expand Down
1 change: 1 addition & 0 deletions spec-main/fixtures/dogs-running.txt

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions spec-main/node-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { expect } from 'chai';
import * as childProcess from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import * as util from 'util';
import { emittedOnce } from './events-helpers';
Expand Down Expand Up @@ -199,6 +200,17 @@ describe('node feature', () => {
});
});

describe('fs.readFile', () => {
it('can accept a FileHandle as the Path argument', async () => {
const filePathForHandle = path.resolve(mainFixturesPath, 'dogs-running.txt');
const fileHandle = await fs.promises.open(filePathForHandle, 'r');

const file = await fs.promises.readFile(fileHandle, { encoding: 'utf8' });
expect(file).to.not.be.empty();
await fileHandle.close();
});
});

ifdescribe(features.isRunAsNodeEnabled())('inspector', () => {
let child: childProcess.ChildProcessWithoutNullStreams;
let exitPromise: Promise<any[]>;
Expand Down

0 comments on commit e3a613d

Please sign in to comment.