From 8d99f53f3dc0815d5515551473367d06669836e0 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Mon, 6 Dec 2021 22:51:08 +0000 Subject: vim-patch:8.2.1083: crash when using reduce() on a NULL list Problem: Crash when using reduce() on a NULL list. Solution: Only access the list when not NULL. https://github.com/vim/vim/commit/fda20c4cc59008264676a6deb6a3095ed0c248e0 CHECK_LIST_MATERIALIZE hasn't been ported yet, but presumably if it is ported it'll use tv_list_first to check for range_list_item, which already checks for NULL, so this should need no extra changes and can be a full port. We didn't actually crash here due to the use of Nvim's tv_list functions checking for NULL, but apply these changes to match Vim better anyway. --- src/nvim/eval/funcs.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'src/nvim/eval/funcs.c') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c80ff8f36a..bd790bfdd3 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7901,22 +7901,25 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, FunPtr fptr) li = tv_list_first(l); } - const VarLockStatus prev_locked = tv_list_locked(l); - const int called_emsg_start = called_emsg; - - tv_list_set_lock(l, VAR_FIXED); // disallow the list changing here tv_copy(&initial, rettv); - for (; li != NULL; li = TV_LIST_ITEM_NEXT(l, li)) { - argv[0] = *rettv; - argv[1] = *TV_LIST_ITEM_TV(li); - rettv->v_type = VAR_UNKNOWN; - const int r = call_func(func_name, -1, rettv, 2, argv, &funcexe); - tv_clear(&argv[0]); - if (r == FAIL || called_emsg != called_emsg_start) { - break; + + if (l != NULL) { + const VarLockStatus prev_locked = tv_list_locked(l); + const int called_emsg_start = called_emsg; + + tv_list_set_lock(l, VAR_FIXED); // disallow the list changing here + for (; li != NULL; li = TV_LIST_ITEM_NEXT(l, li)) { + argv[0] = *rettv; + argv[1] = *TV_LIST_ITEM_TV(li); + rettv->v_type = VAR_UNKNOWN; + const int r = call_func(func_name, -1, rettv, 2, argv, &funcexe); + tv_clear(&argv[0]); + if (r == FAIL || called_emsg != called_emsg_start) { + break; + } } + tv_list_set_lock(l, prev_locked); } - tv_list_set_lock(l, prev_locked); } else { const blob_T *const b = argvars[0].vval.v_blob; int i; -- cgit