fs: validate copyFile paths in the existing C++ binding - #65376
Conversation
|
Review requested:
|
e13ed43 to
8170ff5
Compare
Move path validation, file URL conversion, NUL checks, mode validation, permission checks, and the copy into a dedicated C++ binding so fs.copyFileSync() no longer goes through getValidatedPath() in JavaScript. VFS dispatch stays in JS and still runs before validation. The copy itself uses uv_fs_copyfile, so flags, mode/timestamp preservation, and UV error shapes stay the same. Also fix FileURLToPath aborting on file URLs with a hostname because the ERR_INVALID_FILE_URL_HOST format string lacked %s. Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
8170ff5 to
e4dc3a1
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #65376 +/- ##
==========================================
+ Coverage 90.11% 90.12% +0.01%
==========================================
Files 752 752
Lines 251861 252394 +533
Branches 47365 47457 +92
==========================================
+ Hits 226955 227478 +523
+ Misses 16238 16217 -21
- Partials 8668 8699 +31
🚀 New features to boost your workflow:
|
|
I don't understand this. |
Except getValidatedPath @mcollina |
|
Then why keep both methods? Can't we just fix copyFile and update all usage of that? |
Fold getValidatedPath, file URL conversion, and NUL checks into binding.copyFile so the sync, callback, and promises paths share one implementation. Remove the extra copyFileSync binding. Signed-off-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Yagiz Nizipli <anonrig@users.noreply.github.com>
|
@mcollina you're right — no need for a second binding.
VFS dispatch is still in JS and still runs first. |
mcollina
left a comment
There was a problem hiding this comment.
lgtm
Please update the PR description
| } | ||
|
|
||
| Local<String> path_string; | ||
| if (!String::NewFromUtf8(isolate, |
|
The first commit needs some changes, as it does not reflect what this PR does anymore. |
Move
getValidatedPath, file URL conversion, and NUL checks into the existing C++binding.copyFile.fs.copyFile,fs.copyFileSync, andfs.promises.copyFileall pass the original arguments through.There is no second
copyFileSyncbinding. JavaScript only does VFS dispatch (still before validation). The copy itself usesuv_fs_copyfile, soCOPYFILE_EXCL/FICLONE/FICLONE_FORCE, mode/timestamp preservation, and UV error shapes (syscall: 'copyfile',path/dest) stay the same.This also fixes a crash in the C++
FileURLToPathhelper:ERR_INVALID_FILE_URL_HOSTused a format string without%s, which aborted on file URLs with a hostname. That path is now reachable fromcopyFile/copyFileSync.Performance
Same-binary comparison of the old JS
getValidatedPath+binding.copyFilepath vs the unified C++-validatedbinding.copyFile(n=10000, 9 interleaved repeats, Release):benchmark/fs/bench-copyFileSync.js(n=10000) is dominated byuv_fs_copyfileI/O onvalid(~16k ops/sec) and by ENOENT oninvalid(~260k ops/sec). Those cases stay within a few percent of the old path. The win is validation-bound input (wrong type). Because validation now lives inbinding.copyFile, the callback and promises entry points get the same path — not onlycopyFileSync.Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passesTests
test/parallel/test-fs-copyfile.js(Buffer,Uint8Array,file:URL, non-file URL, encoded slashes, file URL host; callbackcopyFilealso throwsERR_INVALID_URL_SCHEME)test/parallel/test-fs-copyfile-respect-permissions.jstest/parallel/test-fs-null-bytes.jstest/parallel/test-fs-error-messages.jstest/parallel/test-permission-fs-read.js/test-permission-fs-write.jscopyFile/copyFileSynctests