mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
fix(terminal): don't pass incomplete UTF-8 sequence to libvterm (#27922)
This commit is contained in:
parent
c30ebb17f6
commit
16a416cb3c
@ -29,6 +29,7 @@
|
|||||||
#include "nvim/log.h"
|
#include "nvim/log.h"
|
||||||
#include "nvim/lua/executor.h"
|
#include "nvim/lua/executor.h"
|
||||||
#include "nvim/main.h"
|
#include "nvim/main.h"
|
||||||
|
#include "nvim/mbyte.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/message.h"
|
||||||
#include "nvim/msgpack_rpc/channel.h"
|
#include "nvim/msgpack_rpc/channel.h"
|
||||||
@ -646,35 +647,52 @@ static inline list_T *buffer_to_tv_list(const char *const buf, const size_t len)
|
|||||||
void on_channel_data(Stream *stream, RBuffer *buf, size_t count, void *data, bool eof)
|
void on_channel_data(Stream *stream, RBuffer *buf, size_t count, void *data, bool eof)
|
||||||
{
|
{
|
||||||
Channel *chan = data;
|
Channel *chan = data;
|
||||||
on_channel_output(stream, chan, buf, count, eof, &chan->on_data);
|
on_channel_output(stream, chan, buf, eof, &chan->on_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_job_stderr(Stream *stream, RBuffer *buf, size_t count, void *data, bool eof)
|
void on_job_stderr(Stream *stream, RBuffer *buf, size_t count, void *data, bool eof)
|
||||||
{
|
{
|
||||||
Channel *chan = data;
|
Channel *chan = data;
|
||||||
on_channel_output(stream, chan, buf, count, eof, &chan->on_stderr);
|
on_channel_output(stream, chan, buf, eof, &chan->on_stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_channel_output(Stream *stream, Channel *chan, RBuffer *buf, size_t count, bool eof,
|
static void on_channel_output(Stream *stream, Channel *chan, RBuffer *buf, bool eof,
|
||||||
CallbackReader *reader)
|
CallbackReader *reader)
|
||||||
{
|
{
|
||||||
// stub variable, to keep reading consistent with the order of events, only
|
size_t count;
|
||||||
// consider the count parameter.
|
char *output = rbuffer_read_ptr(buf, &count);
|
||||||
size_t r;
|
|
||||||
char *ptr = rbuffer_read_ptr(buf, &r);
|
if (chan->term) {
|
||||||
|
if (!eof) {
|
||||||
|
char *p = output;
|
||||||
|
char *end = output + count;
|
||||||
|
while (p < end) {
|
||||||
|
// Don't pass incomplete UTF-8 sequences to libvterm. #16245
|
||||||
|
// Composing chars can be passed separately, so utf_ptr2len_len() is enough.
|
||||||
|
int clen = utf_ptr2len_len(p, (int)(end - p));
|
||||||
|
if (clen > end - p) {
|
||||||
|
count = (size_t)(p - output);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p += clen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal_receive(chan->term, output, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count) {
|
||||||
|
rbuffer_consumed(buf, count);
|
||||||
|
}
|
||||||
|
// Move remaining data to start of buffer, so the buffer can never wrap around.
|
||||||
|
rbuffer_reset(buf);
|
||||||
|
|
||||||
|
if (callback_reader_set(*reader)) {
|
||||||
|
ga_concat_len(&reader->buffer, output, count);
|
||||||
|
}
|
||||||
|
|
||||||
if (eof) {
|
if (eof) {
|
||||||
reader->eof = true;
|
reader->eof = true;
|
||||||
} else {
|
|
||||||
if (chan->term) {
|
|
||||||
terminal_receive(chan->term, ptr, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
rbuffer_consumed(buf, count);
|
|
||||||
|
|
||||||
if (callback_reader_set(*reader)) {
|
|
||||||
ga_concat_len(&reader->buffer, ptr, count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback_reader_set(*reader)) {
|
if (callback_reader_set(*reader)) {
|
||||||
|
@ -49,6 +49,10 @@ int main(int argc, char **argv)
|
|||||||
help();
|
help();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (argc >= 2) {
|
if (argc >= 2) {
|
||||||
if (strcmp(argv[1], "-t") == 0) {
|
if (strcmp(argv[1], "-t") == 0) {
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
|
@ -10,6 +10,7 @@ local pcall_err = helpers.pcall_err
|
|||||||
local eq, neq = helpers.eq, helpers.neq
|
local eq, neq = helpers.eq, helpers.neq
|
||||||
local api = helpers.api
|
local api = helpers.api
|
||||||
local retry = helpers.retry
|
local retry = helpers.retry
|
||||||
|
local testprg = helpers.testprg
|
||||||
local write_file = helpers.write_file
|
local write_file = helpers.write_file
|
||||||
local command = helpers.command
|
local command = helpers.command
|
||||||
local exc_exec = helpers.exc_exec
|
local exc_exec = helpers.exc_exec
|
||||||
@ -395,6 +396,20 @@ describe(':terminal buffer', function()
|
|||||||
eq('a' .. composing:rep(5), api.nvim_get_current_line())
|
eq('a' .. composing:rep(5), api.nvim_get_current_line())
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('handles split UTF-8 sequences #16245', function()
|
||||||
|
local screen = Screen.new(50, 7)
|
||||||
|
screen:attach()
|
||||||
|
fn.termopen({ testprg('shell-test'), 'UTF-8' })
|
||||||
|
screen:expect([[
|
||||||
|
^å |
|
||||||
|
ref: å̲ |
|
||||||
|
1: å̲ |
|
||||||
|
2: å̲ |
|
||||||
|
3: å̲ |
|
||||||
|
|*2
|
||||||
|
]])
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('on_lines does not emit out-of-bounds line indexes when', function()
|
describe('on_lines does not emit out-of-bounds line indexes when', function()
|
||||||
|
Loading…
Reference in New Issue
Block a user