mirror of
https://github.com/neovim/neovim.git
synced 2026-05-03 12:35:00 +00:00
xstrlcat: Allow overlapped pointers. (#6017)
memcpy is not equivalent to memmove (which is used by vim_strcat), this could cause subtle bugs if xstrlcat is used as a replacement for vim_strcat. But vim_strcat is inconsistent: in the `else` branch it uses strcpy, which doesn't allow overlap. Helped-by: oni-link <knil.ino@gmail.com> Helped-by: James McCoy <jamessan@jamessan.com> Helped-by: Nikolai Aleksandrovich Pavlov <kp-pav@yandex.ru>
This commit is contained in:
51
test/unit/memory_spec.lua
Normal file
51
test/unit/memory_spec.lua
Normal file
@@ -0,0 +1,51 @@
|
||||
local helpers = require("test.unit.helpers")
|
||||
|
||||
local cimport = helpers.cimport
|
||||
local cstr = helpers.cstr
|
||||
local eq = helpers.eq
|
||||
local ffi = helpers.ffi
|
||||
local to_cstr = helpers.to_cstr
|
||||
|
||||
local cimp = cimport('stdlib.h', './src/nvim/memory.h')
|
||||
|
||||
describe('xstrlcat()', function()
|
||||
local function test_xstrlcat(dst, src, dsize)
|
||||
assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests
|
||||
local dst_cstr = cstr(dsize, dst)
|
||||
local src_cstr = to_cstr(src)
|
||||
eq(string.len(dst .. src), cimp.xstrlcat(dst_cstr, src_cstr, dsize))
|
||||
return ffi.string(dst_cstr)
|
||||
end
|
||||
|
||||
local function test_xstrlcat_overlap(dst, src_idx, dsize)
|
||||
assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests
|
||||
local dst_cstr = cstr(dsize, dst)
|
||||
local src_cstr = dst_cstr + src_idx -- pointer into `dst` (overlaps)
|
||||
eq(string.len(dst) + string.len(dst) - src_idx,
|
||||
cimp.xstrlcat(dst_cstr, src_cstr, dsize))
|
||||
return ffi.string(dst_cstr)
|
||||
end
|
||||
|
||||
it('concatenates strings', function()
|
||||
eq('ab', test_xstrlcat('a', 'b', 3))
|
||||
eq('ab', test_xstrlcat('a', 'b', 4096))
|
||||
eq('ABCיהZdefgiיהZ', test_xstrlcat('ABCיהZ', 'defgiיהZ', 4096))
|
||||
eq('b', test_xstrlcat('', 'b', 4096))
|
||||
eq('a', test_xstrlcat('a', '', 4096))
|
||||
end)
|
||||
|
||||
it('concatenates overlapping strings', function()
|
||||
eq('abcabc', test_xstrlcat_overlap('abc', 0, 7))
|
||||
eq('abca', test_xstrlcat_overlap('abc', 0, 5))
|
||||
eq('abcb', test_xstrlcat_overlap('abc', 1, 5))
|
||||
eq('abcc', test_xstrlcat_overlap('abc', 2, 10))
|
||||
eq('abcabc', test_xstrlcat_overlap('abc', 0, 2343))
|
||||
end)
|
||||
|
||||
it('truncates if `dsize` is too small', function()
|
||||
eq('a', test_xstrlcat('a', 'b', 2))
|
||||
eq('', test_xstrlcat('', 'b', 1))
|
||||
eq('ABCיהZd', test_xstrlcat('ABCיהZ', 'defgiיהZ', 10))
|
||||
end)
|
||||
|
||||
end)
|
||||
Reference in New Issue
Block a user