win,tty: fix MultiByteToWideChar output buffer
Make sure there's enough room in the output buffer by dynamically allocating memory in case the size of the buffer needs to be greater than 8192 characters. PR-URL: https://github.com/libuv/libuv/pull/1143 Refs: https://github.com/libuv/libuv/pull/1138 Refs: https://github.com/libuv/libuv/pull/889 Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com> Reviewed-By: Imran Iqbal <imran@imraniqbal.org>
This commit is contained in:
parent
445e3a1f06
commit
c2f0e4f64e
@ -56,6 +56,7 @@
|
||||
#define ANSI_BACKSLASH_SEEN 0x80
|
||||
|
||||
#define MAX_INPUT_BUFFER_LENGTH 8192
|
||||
#define MAX_CONSOLE_CHAR 8192
|
||||
|
||||
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||
@ -1616,17 +1617,29 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
||||
DWORD* error) {
|
||||
/* We can only write 8k characters at a time. Windows can't handle */
|
||||
/* much more characters in a single console write anyway. */
|
||||
WCHAR utf16_buf[8192];
|
||||
WCHAR utf16_buf[MAX_CONSOLE_CHAR];
|
||||
WCHAR* utf16_buffer;
|
||||
DWORD utf16_buf_used = 0;
|
||||
unsigned int i;
|
||||
unsigned int i, len, max_len, pos;
|
||||
int allocate = 0;
|
||||
|
||||
#define FLUSH_TEXT() \
|
||||
do { \
|
||||
if (utf16_buf_used > 0) { \
|
||||
uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \
|
||||
utf16_buf_used = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
#define FLUSH_TEXT() \
|
||||
do { \
|
||||
pos = 0; \
|
||||
do { \
|
||||
len = utf16_buf_used - pos; \
|
||||
if (len > MAX_CONSOLE_CHAR) \
|
||||
len = MAX_CONSOLE_CHAR; \
|
||||
uv_tty_emit_text(handle, &utf16_buffer[pos], len, error); \
|
||||
pos += len; \
|
||||
} while (pos < utf16_buf_used); \
|
||||
if (allocate) { \
|
||||
uv__free(utf16_buffer); \
|
||||
allocate = 0; \
|
||||
utf16_buffer = utf16_buf; \
|
||||
} \
|
||||
utf16_buf_used = 0; \
|
||||
} while (0)
|
||||
|
||||
#define ENSURE_BUFFER_SPACE(wchars_needed) \
|
||||
if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) { \
|
||||
@ -1644,39 +1657,48 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
||||
/* state. */
|
||||
*error = ERROR_SUCCESS;
|
||||
|
||||
utf16_buffer = utf16_buf;
|
||||
|
||||
uv_sem_wait(&uv_tty_output_lock);
|
||||
|
||||
for (i = 0; i < nbufs; i++) {
|
||||
uv_buf_t buf = bufs[i];
|
||||
unsigned int j;
|
||||
|
||||
if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) {
|
||||
utf16_buf_used = MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
buf.base,
|
||||
buf.len,
|
||||
NULL,
|
||||
0);
|
||||
if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) {
|
||||
utf16_buf_used = MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
buf.base,
|
||||
buf.len,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
if (utf16_buf_used == 0) {
|
||||
*error = GetLastError();
|
||||
break;
|
||||
if (utf16_buf_used == 0) {
|
||||
*error = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
max_len = (utf16_buf_used + 1) * sizeof(WCHAR);
|
||||
allocate = max_len > MAX_CONSOLE_CHAR;
|
||||
if (allocate)
|
||||
utf16_buffer = uv__malloc(max_len);
|
||||
if (!MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
buf.base,
|
||||
buf.len,
|
||||
utf16_buffer,
|
||||
utf16_buf_used)) {
|
||||
if (allocate)
|
||||
uv__free(utf16_buffer);
|
||||
*error = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
FLUSH_TEXT();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
buf.base,
|
||||
buf.len,
|
||||
utf16_buf,
|
||||
utf16_buf_used)) {
|
||||
*error = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
FLUSH_TEXT();
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < buf.len; j++) {
|
||||
unsigned char c = buf.base[j];
|
||||
|
||||
|
||||
@ -48,6 +48,7 @@ TEST_DECLARE (tty)
|
||||
#ifdef _WIN32
|
||||
TEST_DECLARE (tty_raw)
|
||||
TEST_DECLARE (tty_empty_write)
|
||||
TEST_DECLARE (tty_large_write)
|
||||
#endif
|
||||
TEST_DECLARE (tty_file)
|
||||
TEST_DECLARE (tty_pty)
|
||||
@ -406,6 +407,7 @@ TASK_LIST_START
|
||||
#ifdef _WIN32
|
||||
TEST_ENTRY (tty_raw)
|
||||
TEST_ENTRY (tty_empty_write)
|
||||
TEST_ENTRY (tty_large_write)
|
||||
#endif
|
||||
TEST_ENTRY (tty_file)
|
||||
TEST_ENTRY (tty_pty)
|
||||
|
||||
@ -217,11 +217,15 @@ TEST_IMPL(tty_empty_write) {
|
||||
int r;
|
||||
int ttyout_fd;
|
||||
uv_tty_t tty_out;
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
char dummy[1];
|
||||
uv_buf_t bufs[1];
|
||||
uv_loop_t* loop;
|
||||
|
||||
/* Make sure we have an FD that refers to a tty */
|
||||
HANDLE handle;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
handle = CreateFileA("conout$",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
@ -239,8 +243,6 @@ TEST_IMPL(tty_empty_write) {
|
||||
r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 0); /* Writable. */
|
||||
ASSERT(r == 0);
|
||||
|
||||
char dummy[1];
|
||||
uv_buf_t bufs[1];
|
||||
bufs[0].len = 0;
|
||||
bufs[0].base = &dummy;
|
||||
|
||||
@ -254,6 +256,49 @@ TEST_IMPL(tty_empty_write) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(tty_large_write) {
|
||||
int r;
|
||||
int ttyout_fd;
|
||||
uv_tty_t tty_out;
|
||||
char dummy[10000];
|
||||
uv_buf_t bufs[1];
|
||||
uv_loop_t* loop;
|
||||
|
||||
/* Make sure we have an FD that refers to a tty */
|
||||
HANDLE handle;
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
handle = CreateFileA("conout$",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
ASSERT(handle != INVALID_HANDLE_VALUE);
|
||||
ttyout_fd = _open_osfhandle((intptr_t) handle, 0);
|
||||
|
||||
ASSERT(ttyout_fd >= 0);
|
||||
|
||||
ASSERT(UV_TTY == uv_guess_handle(ttyout_fd));
|
||||
|
||||
r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 0); /* Writable. */
|
||||
ASSERT(r == 0);
|
||||
|
||||
bufs[0] = uv_buf_init(dummy, sizeof(dummy));
|
||||
|
||||
r = uv_try_write((uv_stream_t*) &tty_out, bufs, 1);
|
||||
ASSERT(r == 10000);
|
||||
|
||||
uv_close((uv_handle_t*) &tty_out, NULL);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user