diff options
author | ZyX <kp-pav@yandex.ru> | 2015-09-06 05:31:04 +0300 |
---|---|---|
committer | ZyX <kp-pav@yandex.ru> | 2015-10-08 22:01:07 +0300 |
commit | d283e758ea8646d92a53cebb457f16a0ddf49d75 (patch) | |
tree | b3a7295498ad81f2a5cb059191c4ba581fd39e8a | |
parent | 690d280fa8d7fd98969fa3fc5bae09a2cd928da6 (diff) | |
download | rneovim-d283e758ea8646d92a53cebb457f16a0ddf49d75.tar.gz rneovim-d283e758ea8646d92a53cebb457f16a0ddf49d75.tar.bz2 rneovim-d283e758ea8646d92a53cebb457f16a0ddf49d75.zip |
shada: Fix out-of-bounds array access
It leads to a memory leak as well. May overwrite wms->jumps_size.
-rw-r--r-- | src/nvim/shada.c | 5 | ||||
-rw-r--r-- | test/functional/shada/merging_spec.lua | 71 |
2 files changed, 75 insertions, 1 deletions
diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 190e5a6cbe..d6a507eb50 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -1209,8 +1209,11 @@ static inline bool marks_equal(const pos_T a, const pos_T b) if (i > 0) { \ if (jl_len == JUMPLISTSIZE) { \ free_func(jumps[0]); \ + if (i == JUMPLISTSIZE) { \ + i = JUMPLISTSIZE - 1; \ + } \ memmove(&jumps[0], &jumps[1], sizeof(jumps[1]) * (size_t) i); \ - } else { \ + } else if (i != jl_len) { \ memmove(&jumps[i + 1], &jumps[i], \ sizeof(jumps[0]) * (size_t) (jl_len - i)); \ } \ diff --git a/test/functional/shada/merging_spec.lua b/test/functional/shada/merging_spec.lua index 2c3eb72e03..9d0d00f5c6 100644 --- a/test/functional/shada/merging_spec.lua +++ b/test/functional/shada/merging_spec.lua @@ -861,6 +861,41 @@ describe('ShaDa jumps support code', function() end eq(found, #jumps) end) + + it('merges JUMPLISTSIZE jumps when writing', function() + local jumps = {} + local shada = '' + for i = 1,100 do + shada = shada .. ('\008%c\018\131\162mX\195\161f\196\006/a/b/c\161l%c' + ):format(i, i) + jumps[i] = {file='/a/b/c', line=i} + end + wshada(shada) + eq(0, exc_exec(sdrcmd())) + local shada = '' + for i = 1,101 do + local t = i * 2 + shada = shada .. ( + '\008\204%c\019\131\162mX\195\161f\196\006/a/b/c\161l\204%c' + ):format(t, t) + jumps[(t > #jumps + 1) and (#jumps + 1) or t] = {file='/a/b/c', line=t} + end + wshada(shada) + eq(0, exc_exec('wshada ' .. shada_fname)) + local shift = #jumps - 100 + for i = 1,100 do + jumps[i] = jumps[i + shift] + end + local found = 0 + for _, v in ipairs(read_shada_file(shada_fname)) do + if v.type == 8 then + found = found + 1 + eq(jumps[found].file, v.value.f) + eq(jumps[found].line, v.value.l) + end + end + eq(found, 100) + end) end) describe('ShaDa changes support code', function() @@ -919,4 +954,40 @@ describe('ShaDa changes support code', function() end eq(found, #changes) end) + + it('merges JUMPLISTSIZE changes when writing', function() + nvim_command('edit /a/b/c') + nvim_command('keepjumps call setline(1, range(202))') + local changes = {} + local shada = '' + for i = 1,100 do + shada = shada .. ('\011%c\018\131\162mX\195\161f\196\006/a/b/c\161l%c' + ):format(i, i) + changes[i] = {line=i} + end + wshada(shada) + eq(0, exc_exec(sdrcmd())) + local shada = '' + for i = 1,101 do + local t = i * 2 + shada = shada .. ( + '\011\204%c\019\131\162mX\195\161f\196\006/a/b/c\161l\204%c' + ):format(t, t) + changes[(t > #changes + 1) and (#changes + 1) or t] = {line=t} + end + wshada(shada) + eq(0, exc_exec('wshada ' .. shada_fname)) + local shift = #changes - 100 + for i = 1,100 do + changes[i] = changes[i + shift] + end + local found = 0 + for _, v in ipairs(read_shada_file(shada_fname)) do + if v.type == 11 and v.value.f == '/a/b/c' then + found = found + 1 + eq(changes[found].line, v.value.l) + end + end + eq(found, 100) + end) end) |