Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2d35607

Browse filesBrowse files
committed
src: fix exception message encoding on Windows
The printf family of functions do not properly display UTF8 strings well on Windows. Use the appropriate wide character API instead if stderr is a tty. PR-URL: #3288 Fixes: #3284 Reviewed-By: Bert Belder <bertbelder@gmail.com>
1 parent 0a7076b commit 2d35607
Copy full SHA for 2d35607

File tree

Expand file treeCollapse file tree

1 file changed

+45
-13
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

1 file changed

+45
-13
lines changed
Open diff view settings
Collapse file

‎src/node.cc‎

Copy file name to clipboardExpand all lines: src/node.cc
+45-13Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include <stdlib.h>
5252
#include <string.h>
5353
#include <sys/types.h>
54+
#include <vector>
5455

5556
#if defined(NODE_HAVE_I18N_SUPPORT)
5657
#include <unicode/uvernum.h>
@@ -156,6 +157,38 @@ static Isolate* node_isolate = nullptr;
156157
static v8::Platform* default_platform;
157158

158159

160+
static void PrintErrorString(const char* format, ...) {
161+
va_list ap;
162+
va_start(ap, format);
163+
#ifdef _WIN32
164+
HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
165+
166+
// Check if stderr is something other than a tty/console
167+
if (stderr_handle == INVALID_HANDLE_VALUE ||
168+
stderr_handle == nullptr ||
169+
uv_guess_handle(_fileno(stderr)) != UV_TTY) {
170+
vfprintf(stderr, format, ap);
171+
return;
172+
}
173+
174+
// Fill in any placeholders
175+
int n = _vscprintf(format, ap);
176+
std::vector<char> out(n + 1);
177+
vsprintf(out.data(), format, ap);
178+
179+
// Get required wide buffer size
180+
n = MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, nullptr, 0);
181+
182+
std::vector<wchar_t> wbuf(n);
183+
MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, wbuf.data(), n);
184+
WriteConsoleW(stderr_handle, wbuf.data(), n, nullptr, nullptr);
185+
#else
186+
vfprintf(stderr, format, ap);
187+
#endif
188+
va_end(ap);
189+
}
190+
191+
159192
static void CheckImmediate(uv_check_t* handle) {
160193
Environment* env = Environment::from_immediate_check_handle(handle);
161194
HandleScope scope(env->isolate());
@@ -1404,7 +1437,7 @@ void AppendExceptionLine(Environment* env,
14041437
return;
14051438
env->set_printed_error(true);
14061439
uv_tty_reset_mode();
1407-
fprintf(stderr, "\n%s", arrow);
1440+
PrintErrorString("\n%s", arrow);
14081441
}
14091442

14101443

@@ -1432,10 +1465,10 @@ static void ReportException(Environment* env,
14321465
// range errors have a trace member set to undefined
14331466
if (trace.length() > 0 && !trace_value->IsUndefined()) {
14341467
if (arrow.IsEmpty() || !arrow->IsString()) {
1435-
fprintf(stderr, "%s\n", *trace);
1468+
PrintErrorString("%s\n", *trace);
14361469
} else {
14371470
node::Utf8Value arrow_string(env->isolate(), arrow);
1438-
fprintf(stderr, "%s\n%s\n", *arrow_string, *trace);
1471+
PrintErrorString("%s\n%s\n", *arrow_string, *trace);
14391472
}
14401473
} else {
14411474
// this really only happens for RangeErrors, since they're the only
@@ -1456,20 +1489,19 @@ static void ReportException(Environment* env,
14561489
name->IsUndefined()) {
14571490
// Not an error object. Just print as-is.
14581491
node::Utf8Value message(env->isolate(), er);
1459-
fprintf(stderr, "%s\n", *message);
1492+
PrintErrorString("%s\n", *message);
14601493
} else {
14611494
node::Utf8Value name_string(env->isolate(), name);
14621495
node::Utf8Value message_string(env->isolate(), message);
14631496

14641497
if (arrow.IsEmpty() || !arrow->IsString()) {
1465-
fprintf(stderr, "%s: %s\n", *name_string, *message_string);
1498+
PrintErrorString("%s: %s\n", *name_string, *message_string);
14661499
} else {
14671500
node::Utf8Value arrow_string(env->isolate(), arrow);
1468-
fprintf(stderr,
1469-
"%s\n%s: %s\n",
1470-
*arrow_string,
1471-
*name_string,
1472-
*message_string);
1501+
PrintErrorString("%s\n%s: %s\n",
1502+
*arrow_string,
1503+
*name_string,
1504+
*message_string);
14731505
}
14741506
}
14751507
}
@@ -2164,9 +2196,9 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
21642196

21652197
static void OnFatalError(const char* location, const char* message) {
21662198
if (location) {
2167-
fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
2199+
PrintErrorString("FATAL ERROR: %s %s\n", location, message);
21682200
} else {
2169-
fprintf(stderr, "FATAL ERROR: %s\n", message);
2201+
PrintErrorString("FATAL ERROR: %s\n", message);
21702202
}
21712203
fflush(stderr);
21722204
ABORT();
@@ -2985,7 +3017,7 @@ static void RawDebug(const FunctionCallbackInfo<Value>& args) {
29853017
CHECK(args.Length() == 1 && args[0]->IsString() &&
29863018
"must be called with a single string");
29873019
node::Utf8Value message(args.GetIsolate(), args[0]);
2988-
fprintf(stderr, "%s\n", *message);
3020+
PrintErrorString("%s\n", *message);
29893021
fflush(stderr);
29903022
}
29913023

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.