From 579ed9781ecf65c9a2c16d65c374f6b59ec3f4e4 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 4 Dec 2016 22:59:25 +0300 Subject: [PATCH] eval: Make sure that v:_null_dict does not crash dictwatcher*() Ref #4615 --- src/nvim/eval/typval.c | 3 +++ .../ex_cmds/dict_notifications_spec.lua | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index e13ef6320e301a..29062b707b011e 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -791,6 +791,9 @@ void tv_dict_watcher_add(dict_T *const dict, const char *const key_pattern, const size_t key_pattern_len, ufunc_T *const callback) FUNC_ATTR_NONNULL_ARG(2, 4) { + if (dict == NULL) { + return; + } DictWatcher *const watcher = xmalloc(sizeof(DictWatcher)); watcher->key_pattern = xmemdupz(key_pattern, key_pattern_len); watcher->key_pattern_len = key_pattern_len; diff --git a/test/functional/ex_cmds/dict_notifications_spec.lua b/test/functional/ex_cmds/dict_notifications_spec.lua index 825d157a080735..8e53659d5b0986 100644 --- a/test/functional/ex_cmds/dict_notifications_spec.lua +++ b/test/functional/ex_cmds/dict_notifications_spec.lua @@ -255,6 +255,16 @@ describe('dictionary change notifications', function() end) end) + it('silently ignores adds to v:_null_dict', function() + nvim_command([[ + function! g:Watcher1(dict, key, value) + call rpcnotify(g:channel, '1', a:key, a:value) + endfunction + ]]) + eq(0, + exc_exec('call dictwatcheradd(v:_null_dict, "x", "g:Watcher1")')) + end) + describe('errors', function() before_each(function() source([[ @@ -278,6 +288,11 @@ describe('dictionary change notifications', function() exc_exec('call dictwatcherdel(g:, "invalid_key", "g:Watcher2")')) end) + it('fails to remove watcher from v:_null_dict', function() + eq("Vim(call):Couldn't find a watcher matching key and callback", + exc_exec('call dictwatcherdel(v:_null_dict, "x", "g:Watcher2")')) + end) + it("fails to add/remove if the callback doesn't exist", function() eq("Vim(call):Function g:InvalidCb doesn't exist", exc_exec('call dictwatcheradd(g:, "key", "g:InvalidCb")'))