From 796761136071d554625a00bc7d985672c0be466d Mon Sep 17 00:00:00 2001 From: Richard Lau Date: Fri, 15 Mar 2024 15:36:48 +0000 Subject: [PATCH] fs: fix edge case in readFileSync utf8 fast path Fix a file permissions regression when `fs.readFileSync()` is called in append mode on a file that does not already exist introduced by the fast path for utf8 encoding. --- src/node_file.cc | 2 +- test/parallel/test-fs-read-file-sync.js | 26 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/node_file.cc b/src/node_file.cc index 52c6c0e71f711e..70c37d7f7ddad7 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -2402,7 +2402,7 @@ static void ReadFileUtf8(const FunctionCallbackInfo& args) { if (CheckOpenPermissions(env, path, flags).IsNothing()) return; FS_SYNC_TRACE_BEGIN(open); - file = uv_fs_open(nullptr, &req, *path, flags, O_RDONLY, nullptr); + file = uv_fs_open(nullptr, &req, *path, flags, 0666, nullptr); FS_SYNC_TRACE_END(open); if (req.result < 0) { uv_fs_req_cleanup(&req); diff --git a/test/parallel/test-fs-read-file-sync.js b/test/parallel/test-fs-read-file-sync.js index ee6f34ac4dccfd..e95c96d1c4d25a 100644 --- a/test/parallel/test-fs-read-file-sync.js +++ b/test/parallel/test-fs-read-file-sync.js @@ -24,11 +24,37 @@ require('../common'); const assert = require('assert'); const fs = require('fs'); const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); const fn = fixtures.path('elipses.txt'); +tmpdir.refresh(); const s = fs.readFileSync(fn, 'utf8'); for (let i = 0; i < s.length; i++) { assert.strictEqual(s[i], '\u2026'); } assert.strictEqual(s.length, 10000); + +// Test file permissions set for readFileSync() in append mode. +{ + const expectedMode = 0o666 & ~process.umask(); + + for (const test of [ + { }, + { encoding: 'ascii' }, + { encoding: 'base64' }, + { encoding: 'hex' }, + { encoding: 'latin1' }, + { encoding: 'uTf8' }, // case variation + { encoding: 'utf16le' }, + { encoding: 'utf8' }, + ]) { + const opts = { ...test, flag: 'a+' }; + const file = tmpdir.resolve(`testReadFileSyncAppend${opts.encoding ?? ''}.txt`); + const variant = `for '${file}'`; + + const content = fs.readFileSync(file, opts); + assert.strictEqual(opts.encoding ? content : content.toString(), '', `file contents ${variant}`); + assert.strictEqual(fs.statSync(file).mode & 0o777, expectedMode, `file permissions ${variant}`); + } +}