aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2016-12-14 16:56:00 +0100
committerJustin M. Keyes <justinkz@gmail.com>2016-12-14 20:52:18 +0100
commit43ba7f4d987fc491de3378eef6b246a697c6e0b0 (patch)
tree6ddaa9431640ec0f4767449942b31697963ec8d3
parent8c9cccbcb6bb5ee803f308916d5de1b949e0b13c (diff)
downloadrneovim-43ba7f4d987fc491de3378eef6b246a697c6e0b0.tar.gz
rneovim-43ba7f4d987fc491de3378eef6b246a697c6e0b0.tar.bz2
rneovim-43ba7f4d987fc491de3378eef6b246a697c6e0b0.zip
eval.c: set_selfdict(): Fix invalid memory access.
-rw-r--r--src/nvim/eval.c10
-rw-r--r--test/functional/core/job_spec.lua20
-rw-r--r--test/functional/helpers.lua26
-rw-r--r--test/functional/legacy/061_undo_tree_spec.lua2
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()