aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2016-06-11 21:59:01 +0300
committerZyX <kp-pav@yandex.ru>2016-06-24 16:53:26 +0300
commit0d56118d862f0a366da57c82a6e995f1a51b0fc7 (patch)
tree2d471532a260598076a5a2cb51254f4bf6591639 /src
parent2968dc7bddbe56719bbb918f712de866fa6c230e (diff)
downloadrneovim-0d56118d862f0a366da57c82a6e995f1a51b0fc7.tar.gz
rneovim-0d56118d862f0a366da57c82a6e995f1a51b0fc7.tar.bz2
rneovim-0d56118d862f0a366da57c82a6e995f1a51b0fc7.zip
msgpack_rpc: Fix crash in log_server_msg
It appears that used msgpack library is not able to parse back message created by msgpack_rpc_from_object() if nesting level is too high, so log_server_msg now cares about msgpack_unpack_next() return value. Also error message from server_notifications_spec.lua is not readable if something is wrong (though at least now it does not crash when parsing deeply nested structures). log_server_msg() in the test reports [msgpack-rpc] nvim -> client(1) [error] "parse error"
Diffstat (limited to 'src')
-rw-r--r--src/nvim/msgpack_rpc/channel.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 0d7d5a247e..b14278a554 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -816,20 +816,55 @@ static void decref(Channel *channel)
#define REQ "[request] "
#define RES "[response] "
#define NOT "[notification] "
+#define ERR "[error] "
+
+// Cannot define array with negative offsets, so this one is needed to be added
+// to MSGPACK_UNPACK_\* values.
+#define MUR_OFF 2
+
+static const char *const msgpack_error_messages[] = {
+ [MSGPACK_UNPACK_EXTRA_BYTES + MUR_OFF] = "extra bytes found",
+ [MSGPACK_UNPACK_CONTINUE + MUR_OFF] = "incomplete string",
+ [MSGPACK_UNPACK_PARSE_ERROR + MUR_OFF] = "parse error",
+ [MSGPACK_UNPACK_NOMEM_ERROR + MUR_OFF] = "not enough memory",
+};
static void log_server_msg(uint64_t channel_id,
msgpack_sbuffer *packed)
{
msgpack_unpacked unpacked;
msgpack_unpacked_init(&unpacked);
- msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL);
- uint64_t type = unpacked.data.via.array.ptr[0].via.u64;
DLOGN("[msgpack-rpc] nvim -> client(%" PRIu64 ") ", channel_id);
- log_lock();
- FILE *f = open_log_file();
- fprintf(f, type ? (type == 1 ? RES : NOT) : REQ);
- log_msg_close(f, unpacked.data);
- msgpack_unpacked_destroy(&unpacked);
+ const msgpack_unpack_return result =
+ msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL);
+ switch (result) {
+ case MSGPACK_UNPACK_SUCCESS: {
+ uint64_t type = unpacked.data.via.array.ptr[0].via.u64;
+ log_lock();
+ FILE *f = open_log_file();
+ fprintf(f, type ? (type == 1 ? RES : NOT) : REQ);
+ log_msg_close(f, unpacked.data);
+ msgpack_unpacked_destroy(&unpacked);
+ break;
+ }
+ case MSGPACK_UNPACK_EXTRA_BYTES:
+ case MSGPACK_UNPACK_CONTINUE:
+ case MSGPACK_UNPACK_PARSE_ERROR:
+ case MSGPACK_UNPACK_NOMEM_ERROR: {
+ log_lock();
+ FILE *f = open_log_file();
+ fprintf(f, ERR);
+ log_msg_close(f, (msgpack_object) {
+ .type = MSGPACK_OBJECT_STR,
+ .via.str = {
+ .ptr = (char *) msgpack_error_messages[result + MUR_OFF],
+ .size = (uint32_t) strlen(
+ msgpack_error_messages[result + MUR_OFF]),
+ },
+ });
+ break;
+ }
+ }
}
static void log_client_msg(uint64_t channel_id,