diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-06-17 10:01:26 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-06-17 12:12:29 -0300 |
commit | 063d8a5773b8c0a1a3cac97c7b72c91d560264cf (patch) | |
tree | af56468dd52a1dccee19bb6dba83c5d12df45376 /src/nvim/os/channel.c | |
parent | d199d18159c624844c9c8052d1a98b91084fb803 (diff) | |
download | rneovim-063d8a5773b8c0a1a3cac97c7b72c91d560264cf.tar.gz rneovim-063d8a5773b8c0a1a3cac97c7b72c91d560264cf.tar.bz2 rneovim-063d8a5773b8c0a1a3cac97c7b72c91d560264cf.zip |
msgpack_rpc: Deal with deserialization failures
There seems to be no way to deal with failures when calling
`msgpack_unpacker_next`, so this reimplements that function as
`msgpack_rpc_unpack`, which has an additional result for detecting failures.
On top of that, we make use of the new function to properly return msgpack-rpc
errors when something bad happens.
Diffstat (limited to 'src/nvim/os/channel.c')
-rw-r--r-- | src/nvim/os/channel.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/src/nvim/os/channel.c b/src/nvim/os/channel.c index 9a692cf9fe..b1e2a8a287 100644 --- a/src/nvim/os/channel.c +++ b/src/nvim/os/channel.c @@ -183,11 +183,13 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof) msgpack_unpacked unpacked; msgpack_unpacked_init(&unpacked); + UnpackResult result; + msgpack_packer response; // Deserialize everything we can. - while (msgpack_unpacker_next(channel->unpacker, &unpacked)) { + while ((result = msgpack_rpc_unpack(channel->unpacker, &unpacked)) + == kUnpackResultOk) { // Each object is a new msgpack-rpc request and requires an empty response - msgpack_packer response; msgpack_packer_init(&response, channel->sbuffer, msgpack_sbuffer_write); // Perform the call msgpack_rpc_call(channel->id, &unpacked.data, &response); @@ -199,6 +201,29 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof) // Clear the buffer for future calls msgpack_sbuffer_clear(channel->sbuffer); } + + if (result == kUnpackResultFail) { + // See src/msgpack/unpack_template.h in msgpack source tree for + // causes for this error(search for 'goto _failed') + // + // A not so uncommon cause for this might be deserializing objects with + // a high nesting level: msgpack will break when it's internal parse stack + // size exceeds MSGPACK_EMBED_STACK_SIZE(defined as 32 by default) + msgpack_packer_init(&response, channel->sbuffer, msgpack_sbuffer_write); + msgpack_pack_array(&response, 4); + msgpack_pack_int(&response, 1); + msgpack_pack_int(&response, 0); + msgpack_rpc_error("Invalid msgpack payload. " + "This error can also happen when deserializing " + "an object with high level of nesting", + &response); + wstream_write(channel->data.streams.write, + wstream_new_buffer(channel->sbuffer->data, + channel->sbuffer->size, + true)); + // Clear the buffer for future calls + msgpack_sbuffer_clear(channel->sbuffer); + } } static void send_event(Channel *channel, char *type, typval_T *data) |