diff options
author | ZyX <kp-pav@yandex.ru> | 2016-12-25 23:29:35 +0300 |
---|---|---|
committer | ZyX <kp-pav@yandex.ru> | 2017-01-03 06:39:23 +0300 |
commit | 759e736b0ab03034dc61d6a30e1b8b1f17ed9695 (patch) | |
tree | 92da5c50e05040dbcad881c270ebade0ca1fc502 /src/nvim/eval.c | |
parent | affa3c2baa60acbffd32234326d38cced2d3f30c (diff) | |
download | rneovim-759e736b0ab03034dc61d6a30e1b8b1f17ed9695.tar.gz rneovim-759e736b0ab03034dc61d6a30e1b8b1f17ed9695.tar.bz2 rneovim-759e736b0ab03034dc61d6a30e1b8b1f17ed9695.zip |
eval/typval_encode: Fix infinite loop
Occurs when trying to dump a partial with attached self dictionary which
references that partial. “Infinite” loop should normally result in Neovim killed
by OOM killer.
Also moved the place when partials are unreferenced by clear_tv: from
…FUNC_START to …FUNC_END.
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 8f66976f1c..9546edc87f 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -19072,22 +19072,30 @@ void free_tv(typval_T *varp) #define TYPVAL_ENCODE_CONV_FUNC_START(fun, is_partial, pt) \ do { \ - if (is_partial) { \ - partial_unref(pt); \ - tv->vval.v_partial = NULL; \ - } else { \ + if (!is_partial) { \ func_unref(fun); \ if (fun != empty_string) { \ xfree(fun); \ } \ tv->vval.v_string = NULL; \ + tv->v_lock = VAR_UNLOCKED; \ } \ - tv->v_lock = VAR_UNLOCKED; \ } while (0) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(len) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(len) -#define TYPVAL_ENCODE_CONV_FUNC_END() +#define TYPVAL_ENCODE_CONV_FUNC_END() \ + do { \ + if (cur_mpsv->type == kMPConvPartial) { \ + typval_T *const cur_tv = cur_mpsv->tv; \ + partial_T *const pt = cur_mpsv->data.p.pt; \ + partial_unref(pt); \ + if (cur_tv != NULL) { \ + cur_tv->vval.v_partial = NULL; \ + cur_tv->v_lock = VAR_UNLOCKED; \ + } \ + } \ + } while (0) #define TYPVAL_ENCODE_CONV_EMPTY_LIST() \ do { \ @@ -19118,10 +19126,14 @@ void free_tv(typval_T *varp) #define TYPVAL_ENCODE_CONV_LIST_END() \ do { \ typval_T *const cur_tv = cur_mpsv->tv; \ - assert(cur_tv->v_type == VAR_LIST); \ - list_unref(cur_tv->vval.v_list); \ - cur_tv->vval.v_list = NULL; \ - cur_tv->v_lock = VAR_UNLOCKED; \ + list_T *const list = cur_mpsv->data.l.list; \ + list_unref(list); \ + if (cur_tv != NULL) { \ + assert(list == cur_tv->vval.v_list); \ + assert(cur_tv->v_type == VAR_LIST); \ + cur_tv->vval.v_list = NULL; \ + cur_tv->v_lock = VAR_UNLOCKED; \ + } \ } while (0) #define TYPVAL_ENCODE_CONV_DICT_START(ignored) \ @@ -19143,10 +19155,14 @@ void free_tv(typval_T *varp) #define TYPVAL_ENCODE_CONV_DICT_END() \ do { \ typval_T *const cur_tv = cur_mpsv->tv; \ - assert(cur_tv->v_type == VAR_DICT); \ + dict_T *const dict = cur_mpsv->data.d.dict; \ dict_unref(cur_tv->vval.v_dict); \ - cur_tv->vval.v_dict = NULL; \ - cur_tv->v_lock = VAR_UNLOCKED; \ + if (cur_tv != NULL) { \ + assert(dict == cur_tv->vval.v_dict); \ + assert(cur_tv->v_type == VAR_DICT); \ + cur_tv->vval.v_dict = NULL; \ + cur_tv->v_lock = VAR_UNLOCKED; \ + } \ } while (0) #define TYPVAL_ENCODE_CONV_RECURSE(ignored1, ignored2) |