Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/crypto/crypto_context.cc4
-rw-r--r--src/crypto/crypto_keygen.cc8
-rw-r--r--src/node_binding.cc47
-rw-r--r--test/parallel/test-process-dlopen-error-message-crash.js46
-rw-r--r--test/parallel/test-tls-min-max-version.js5
5 files changed, 74 insertions, 36 deletions
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
index f8ea6f9acca..7eab9de37cb 100644
--- a/src/crypto/crypto_context.cc
+++ b/src/crypto/crypto_context.cc
@@ -501,8 +501,8 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
max_version = TLS1_2_VERSION;
method = TLS_client_method();
} else {
- const std::string msg("Unknown method: ");
- THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(env, (msg + * sslmethod).c_str());
+ THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(
+ env, "Unknown method: %s", *sslmethod);
return;
}
}
diff --git a/src/crypto/crypto_keygen.cc b/src/crypto/crypto_keygen.cc
index e4e9c227458..e8f55806de6 100644
--- a/src/crypto/crypto_keygen.cc
+++ b/src/crypto/crypto_keygen.cc
@@ -68,11 +68,9 @@ Maybe<bool> SecretKeyGenTraits::AdditionalConfig(
params->length = static_cast<size_t>(
std::trunc(args[*offset].As<Uint32>()->Value() / CHAR_BIT));
if (params->length > INT_MAX) {
- const std::string msg{
- SPrintF("length must be less than or equal to %s bits",
- static_cast<uint64_t>(INT_MAX) * CHAR_BIT)
- };
- THROW_ERR_OUT_OF_RANGE(env, msg.c_str());
+ THROW_ERR_OUT_OF_RANGE(env,
+ "length must be less than or equal to %u bits",
+ static_cast<uint64_t>(INT_MAX) * CHAR_BIT);
return Nothing<bool>();
}
*offset += 1;
diff --git a/src/node_binding.cc b/src/node_binding.cc
index 60eca5c9fa5..fa67a45386e 100644
--- a/src/node_binding.cc
+++ b/src/node_binding.cc
@@ -459,7 +459,7 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
// Windows needs to add the filename into the error message
errmsg += *filename;
#endif // _WIN32
- THROW_ERR_DLOPEN_FAILED(env, errmsg.c_str());
+ THROW_ERR_DLOPEN_FAILED(env, "%s", errmsg.c_str());
return false;
}
@@ -484,12 +484,8 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
mp = dlib->GetSavedModuleFromGlobalHandleMap();
if (mp == nullptr || mp->nm_context_register_func == nullptr) {
dlib->Close();
- char errmsg[1024];
- snprintf(errmsg,
- sizeof(errmsg),
- "Module did not self-register: '%s'.",
- *filename);
- THROW_ERR_DLOPEN_FAILED(env, errmsg);
+ THROW_ERR_DLOPEN_FAILED(
+ env, "Module did not self-register: '%s'.", *filename);
return false;
}
}
@@ -504,23 +500,22 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
callback(exports, module, context);
return true;
}
- char errmsg[1024];
- snprintf(errmsg,
- sizeof(errmsg),
- "The module '%s'"
- "\nwas compiled against a different Node.js version using"
- "\nNODE_MODULE_VERSION %d. This version of Node.js requires"
- "\nNODE_MODULE_VERSION %d. Please try re-compiling or "
- "re-installing\nthe module (for instance, using `npm rebuild` "
- "or `npm install`).",
- *filename,
- mp->nm_version,
- NODE_MODULE_VERSION);
+ const int actual_nm_version = mp->nm_version;
// NOTE: `mp` is allocated inside of the shared library's memory, calling
// `dlclose` will deallocate it
dlib->Close();
- THROW_ERR_DLOPEN_FAILED(env, errmsg);
+ THROW_ERR_DLOPEN_FAILED(
+ env,
+ "The module '%s'"
+ "\nwas compiled against a different Node.js version using"
+ "\nNODE_MODULE_VERSION %d. This version of Node.js requires"
+ "\nNODE_MODULE_VERSION %d. Please try re-compiling or "
+ "re-installing\nthe module (for instance, using `npm rebuild` "
+ "or `npm install`).",
+ *filename,
+ actual_nm_version,
+ NODE_MODULE_VERSION);
return false;
}
CHECK_EQ(mp->nm_flags & NM_F_BUILTIN, 0);
@@ -600,9 +595,7 @@ void GetInternalBinding(const FunctionCallbackInfo<Value>& args) {
builtins::BuiltinLoader::GetConfigString(env->isolate()))
.FromJust());
} else {
- char errmsg[1024];
- snprintf(errmsg, sizeof(errmsg), "No such module: %s", *module_v);
- return THROW_ERR_INVALID_MODULE(env, errmsg);
+ return THROW_ERR_INVALID_MODULE(env, "No such module: %s", *module_v);
}
args.GetReturnValue().Set(exports);
@@ -632,12 +625,8 @@ void GetLinkedBinding(const FunctionCallbackInfo<Value>& args) {
mod = FindModule(modlist_linked, name, NM_F_LINKED);
if (mod == nullptr) {
- char errmsg[1024];
- snprintf(errmsg,
- sizeof(errmsg),
- "No such module was linked: %s",
- *module_name_v);
- return THROW_ERR_INVALID_MODULE(env, errmsg);
+ return THROW_ERR_INVALID_MODULE(
+ env, "No such module was linked: %s", *module_name_v);
}
Local<Object> module = Object::New(env->isolate());
diff --git a/test/parallel/test-process-dlopen-error-message-crash.js b/test/parallel/test-process-dlopen-error-message-crash.js
new file mode 100644
index 00000000000..d678021764e
--- /dev/null
+++ b/test/parallel/test-process-dlopen-error-message-crash.js
@@ -0,0 +1,46 @@
+'use strict';
+
+// This is a regression test for some scenarios in which node would pass
+// unsanitized user input to a printf-like formatting function when dlopen
+// fails, potentially crashing the process.
+
+const common = require('../common');
+const tmpdir = require('../common/tmpdir');
+tmpdir.refresh();
+
+const assert = require('assert');
+const fs = require('fs');
+
+// This error message should not be passed to a printf-like function.
+assert.throws(() => {
+ process.dlopen({ exports: {} }, 'foo-%s.node');
+}, ({ name, code, message }) => {
+ assert.strictEqual(name, 'Error');
+ assert.strictEqual(code, 'ERR_DLOPEN_FAILED');
+ if (!common.isAIX) {
+ assert.match(message, /foo-%s\.node/);
+ }
+ return true;
+});
+
+const notBindingDir = 'test/addons/not-a-binding';
+const notBindingPath = `${notBindingDir}/build/Release/binding.node`;
+const strangeBindingPath = `${tmpdir.path}/binding-%s.node`;
+// Ensure that the addon directory exists, but skip the remainder of the test if
+// the addon has not been compiled.
+fs.accessSync(notBindingDir);
+try {
+ fs.copyFileSync(notBindingPath, strangeBindingPath);
+} catch (err) {
+ if (err.code !== 'ENOENT') throw err;
+ common.skip(`addon not found: ${notBindingPath}`);
+}
+
+// This error message should also not be passed to a printf-like function.
+assert.throws(() => {
+ process.dlopen({ exports: {} }, strangeBindingPath);
+}, {
+ name: 'Error',
+ code: 'ERR_DLOPEN_FAILED',
+ message: /^Module did not self-register: '.*binding-%s\.node'\.$/
+});
diff --git a/test/parallel/test-tls-min-max-version.js b/test/parallel/test-tls-min-max-version.js
index 8dbef1fa37a..ff337961f9a 100644
--- a/test/parallel/test-tls-min-max-version.js
+++ b/test/parallel/test-tls-min-max-version.js
@@ -97,6 +97,11 @@ test(U, U, 'hokey-pokey', U, U, U,
test(U, U, U, U, U, 'hokey-pokey',
U, U, 'ERR_TLS_INVALID_PROTOCOL_METHOD');
+// Regression test: this should not crash because node should not pass the error
+// message (including unsanitized user input) to a printf-like function.
+test(U, U, U, U, U, '%s_method',
+ U, U, 'ERR_TLS_INVALID_PROTOCOL_METHOD');
+
// Cannot use secureProtocol and min/max versions simultaneously.
test(U, U, U, U, 'TLSv1.2', 'TLS1_2_method',
U, U, 'ERR_TLS_PROTOCOL_VERSION_CONFLICT');