aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/channel.c
diff options
context:
space:
mode:
authorThiago de Arruda <tpadilha84@gmail.com>2014-06-17 10:01:26 -0300
committerThiago de Arruda <tpadilha84@gmail.com>2014-06-17 12:12:29 -0300
commit063d8a5773b8c0a1a3cac97c7b72c91d560264cf (patch)
treeaf56468dd52a1dccee19bb6dba83c5d12df45376 /src/nvim/os/channel.c
parentd199d18159c624844c9c8052d1a98b91084fb803 (diff)
downloadrneovim-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.c29
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)