fix: improper wrapping of fs.promises.readFile (#29528)

This commit is contained in:
Shelley Vohr 2021-06-07 21:19:39 +02:00 committed by GitHub
parent 5665738ceb
commit a4decffe9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 50 deletions

View file

@ -489,63 +489,83 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
}
};
function fsReadFileAsar (pathArgument: string, options: any, callback: any) {
const pathInfo = splitPath(pathArgument);
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');
}
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;
}
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);
}
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 { readFile } = fs;
fs.readFile = function (pathArgument: string, options: any, callback: any) {
const pathInfo = splitPath(pathArgument);
if (!pathInfo.isAsar) return readFile.apply(this, arguments);
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 (!pathInfo.isAsar) {
return readFile.apply(this, arguments);
}
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;
}
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);
}
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);
});
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) {

File diff suppressed because one or more lines are too long

View file

@ -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';
@ -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[]>;