From b22802a148c43b5a7ed56dd23ed92ded281cb498 Mon Sep 17 00:00:00 2001 From: Carlos Menezes Date: Fri, 16 May 2025 18:18:31 +0100 Subject: [PATCH] process: better error for cwd() in empty dir --- doc/api/errors.md | 17 +++++++-- src/node_errors.h | 2 ++ src/node_process_methods.cc | 4 +++ test/parallel/test-cwd-deleted.js | 45 ++++++++++++++++++++++++ test/parallel/test-cwd-enoent-preload.js | 2 +- 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 test/parallel/test-cwd-deleted.js diff --git a/doc/api/errors.md b/doc/api/errors.md index ccf8d16655cec4..d87de88f519e9f 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -189,7 +189,7 @@ a string representing the location in the code at which ```js const myObject = {}; Error.captureStackTrace(myObject); -myObject.stack; // Similar to `new Error().stack` +myObject.stack; // Similar to `new Error().stack` ``` The first line of the trace will be prefixed with @@ -600,7 +600,7 @@ Indicates that a provided argument is not an allowable type. For example, passing a function to a parameter which expects a string would be a `TypeError`. ```js -require('node:url').parse(() => { }); +require('node:url').parse(() => {}); // Throws TypeError, since it expected a string. ``` @@ -1121,6 +1121,17 @@ added: An attempt to invoke an unsupported crypto operation was made. + + +### `ERR_CWD_DELETED` + + + +`process.cwd()` was called on a directory that no longer exists. + ### `ERR_DEBUGGER_ERROR` @@ -2935,7 +2946,7 @@ The context must be a `SecureContext`. ### `ERR_TLS_INVALID_PROTOCOL_METHOD` -The specified `secureProtocol` method is invalid. It is either unknown, or +The specified `secureProtocol` method is invalid. It is either unknown, or disabled because it is insecure. diff --git a/src/node_errors.h b/src/node_errors.h index 4d7132a9954505..aaa8b6fb7b49fb 100644 --- a/src/node_errors.h +++ b/src/node_errors.h @@ -71,6 +71,7 @@ void OOMErrorHandler(const char* location, const v8::OOMDetails& details); V(ERR_CRYPTO_UNKNOWN_DH_GROUP, Error) \ V(ERR_CRYPTO_UNSUPPORTED_OPERATION, Error) \ V(ERR_CRYPTO_JOB_INIT_FAILED, Error) \ + V(ERR_CWD_DELETED, Error) \ V(ERR_DLOPEN_DISABLED, Error) \ V(ERR_DLOPEN_FAILED, Error) \ V(ERR_ENCODING_INVALID_ENCODED_DATA, TypeError) \ @@ -203,6 +204,7 @@ ERRORS_WITH_CODE(V) V(ERR_CRYPTO_UNKNOWN_DH_GROUP, "Unknown DH group") \ V(ERR_CRYPTO_UNSUPPORTED_OPERATION, "Unsupported crypto operation") \ V(ERR_CRYPTO_JOB_INIT_FAILED, "Failed to initialize crypto job config") \ + V(ERR_CWD_DELETED, "Current working directory has been deleted") \ V(ERR_DLOPEN_FAILED, "DLOpen failed") \ V(ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE, \ "Context not associated with Node.js environment") \ diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc index 9dd936c8ba9dcf..1ccfffb1906770 100644 --- a/src/node_process_methods.cc +++ b/src/node_process_methods.cc @@ -163,6 +163,10 @@ static void Cwd(const FunctionCallbackInfo& args) { size_t cwd_len = sizeof(buf); int err = uv_cwd(buf, &cwd_len); if (err) { + if (err == UV_ENOENT) { + return THROW_ERR_CWD_DELETED(env); + } + return env->ThrowUVException(err, "uv_cwd"); } diff --git a/test/parallel/test-cwd-deleted.js b/test/parallel/test-cwd-deleted.js new file mode 100644 index 00000000000000..02d128724e33df --- /dev/null +++ b/test/parallel/test-cwd-deleted.js @@ -0,0 +1,45 @@ +'use strict'; + +const common = require('../common'); + +// Removing the current working directory is not supported on all platforms. +if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) { + common.skip('cannot rmdir current working directory on this platform'); +} + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('process.chdir is not available in Workers'); +} + +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const tmpdir = require('../common/tmpdir'); + +tmpdir.refresh(); +const dirname = path.join(tmpdir.path, `cwd-deleted-test-${process.pid}`); +const originalCwd = process.cwd(); + +fs.mkdirSync(dirname); +process.chdir(dirname); + +try { + fs.rmdirSync(dirname); +} catch (err) { + process.chdir(originalCwd); + common.skip(`rmdir failed: ${err.message}. Skipping test.`); +} + +assert.throws( + () => { + process.cwd(); + }, + { + name: 'Error', + message: 'Current working directory has been deleted', + } +); + +process.chdir(originalCwd); diff --git a/test/parallel/test-cwd-enoent-preload.js b/test/parallel/test-cwd-enoent-preload.js index a7841e984d0eab..c6b542979001c6 100644 --- a/test/parallel/test-cwd-enoent-preload.js +++ b/test/parallel/test-cwd-enoent-preload.js @@ -30,6 +30,6 @@ proc.stdout.pipe(process.stdout); proc.stderr.pipe(process.stderr); proc.once('exit', common.mustCall(function(exitCode, signalCode) { - assert.strictEqual(exitCode, 0); + assert.strictEqual(exitCode, 1); assert.strictEqual(signalCode, null); }));