diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2016-12-14 16:56:00 +0100 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2016-12-14 20:52:18 +0100 |
commit | 43ba7f4d987fc491de3378eef6b246a697c6e0b0 (patch) | |
tree | 6ddaa9431640ec0f4767449942b31697963ec8d3 | |
parent | 8c9cccbcb6bb5ee803f308916d5de1b949e0b13c (diff) | |
download | rneovim-43ba7f4d987fc491de3378eef6b246a697c6e0b0.tar.gz rneovim-43ba7f4d987fc491de3378eef6b246a697c6e0b0.tar.bz2 rneovim-43ba7f4d987fc491de3378eef6b246a697c6e0b0.zip |
eval.c: set_selfdict(): Fix invalid memory access.
-rw-r--r-- | src/nvim/eval.c | 10 | ||||
-rw-r--r-- | test/functional/core/job_spec.lua | 20 | ||||
-rw-r--r-- | test/functional/helpers.lua | 26 | ||||
-rw-r--r-- | test/functional/legacy/061_undo_tree_spec.lua | 2 |
4 files changed, 44 insertions, 14 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index a205c37d6e..982074f62a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -18665,15 +18665,17 @@ handle_subscript ( return ret; } -static void set_selfdict(typval_T *rettv, dict_T *selfdict) { +static void set_selfdict(typval_T *rettv, dict_T *selfdict) +{ // Don't do this when "dict.Func" is already a partial that was bound // explicitly (pt_auto is false). if (rettv->v_type == VAR_PARTIAL && !rettv->vval.v_partial->pt_auto && rettv->vval.v_partial->pt_dict != NULL) { return; } - char_u *fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string - : rettv->vval.v_partial->pt_name; + char_u *fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING + ? rettv->vval.v_string + : rettv->vval.v_partial->pt_name; char_u *tofree = NULL; ufunc_T *fp; char_u fname_buf[FLEN_FIXED + 1]; @@ -18694,7 +18696,7 @@ static void set_selfdict(typval_T *rettv, dict_T *selfdict) { pt->pt_dict = selfdict; (selfdict->dv_refcount)++; pt->pt_auto = true; - if (rettv->v_type == VAR_FUNC) { + if (rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING) { // Just a function: Take over the function name and use selfdict. pt->pt_name = rettv->vval.v_string; } else { diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index fa38671529..e27adc1a51 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -303,6 +303,26 @@ describe('jobs', function() ]]) end) + it('requires funcrefs for script-local (s:) functions', function() + -- Pass job callback names _without_ `function(...)`. + source([[ + function! s:OnEvent(id, data, event) dict + let g:job_result = get(self, 'user') + endfunction + let s:job = jobstart(['echo'], { + \ 'on_stdout': 's:OnEvent', + \ 'on_stderr': 's:OnEvent', + \ 'on_exit': 's:OnEvent', + \ 'user': 2349 + \ }) + ]]) + + -- The behavior is asynchronous, retry until a time limit. + helpers.retry(nil, 10000, function() + eq("E120:", string.match(eval("v:errmsg"), "E%d*:")) + end) + end) + describe('jobwait', function() it('returns a list of status codes', function() source([[ diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index d1ab02f361..f3332cff4f 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -1,4 +1,5 @@ require('coxpcall') +local luv = require('luv') local lfs = require('lfs') local global_helpers = require('test.helpers') @@ -243,17 +244,24 @@ local function connect(file_or_address) return Session.new(stream) end --- Calls fn() until it returns without error, up to `max` times. -local function retry(fn, max) - local retries = max and (max - 1) or 2 - for _ = 1, retries do - local success = pcall(fn) - if success then - return +-- Calls fn() until it succeeds, up to `max` times or until `max_ms` +-- milliseconds have passed. +local function retry(max, max_ms, fn) + local tries = 1 + local timeout = (max_ms and max_ms > 0) and max_ms or 10000 + local start_time = luv.now() + while true do + local status, result = pcall(fn) + if status then + return result + end + if (max and tries >= max) or (luv.now() - start_time > timeout) then + break end + tries = tries + 1 end - -- pcall() is not used for the final attempt so failure can bubble up. - fn() + -- Do not use pcall() for the final attempt, let the failure bubble up. + return fn() end local function clear(...) diff --git a/test/functional/legacy/061_undo_tree_spec.lua b/test/functional/legacy/061_undo_tree_spec.lua index 2069204938..aeb2001d11 100644 --- a/test/functional/legacy/061_undo_tree_spec.lua +++ b/test/functional/legacy/061_undo_tree_spec.lua @@ -98,7 +98,7 @@ describe('undo tree:', function() expect_line('123456abc') end - helpers.retry(test_earlier_later) + helpers.retry(2, nil, test_earlier_later) end) it('file-write specifications', function() |