vim-patch:9.1.1943: Memory leak with :breakadd expr

Problem:  Memory leak with :breakadd expr
Solution: Free debug_oldval and debug_newval before assigning to them.
          Verify the existing (though confusing) :breakadd expr behavior
          (zeertzjq).

It seems that :breakadd expr doesn't work as documented at all. This PR
only fixes the memory leak. The tests are for the existing behavior.

closes: vim/vim#18844

a474de64df
This commit is contained in:
zeertzjq
2025-12-02 06:50:30 +08:00
parent 62de643b89
commit b64e36cef0
3 changed files with 142 additions and 49 deletions

View File

@@ -13,64 +13,112 @@ describe('debugger', function()
local screen
before_each(function()
screen = Screen.new(999, 10)
screen = Screen.new(999, 7)
end)
-- oldtest: Test_Debugger_breakadd_expr()
-- This doesn't seem to work as documented. The breakpoint is not
-- triggered until the next function call.
it(':breakadd expr', function()
write_file('XdebugBreakExpr.vim', 'let g:Xtest_var += 1')
write_file(
'XbreakExpr.vim',
[[
func Foo()
eval 1
eval 2
endfunc
let g:Xtest_var += 1
call Foo()
let g:Xtest_var += 1
call Foo()]]
)
finally(function()
os.remove('XdebugBreakExpr.vim')
os.remove('XbreakExpr.vim')
end)
command('edit XdebugBreakExpr.vim')
command('edit XbreakExpr.vim')
command(':let g:Xtest_var = 10')
command(':breakadd expr g:Xtest_var')
feed(':source %<CR>')
screen:expect {
grid = [[
^let g:Xtest_var += 1{MATCH: *}|
{1:~{MATCH: *}}|*8
:source %{MATCH: *}|
]],
}
feed(':source %<CR>')
screen:expect {
grid = [[
local initial_screen = [[
^func Foo(){MATCH: *}|
eval 1{MATCH: *}|
eval 2{MATCH: *}|
endfunc{MATCH: *}|
{MATCH: *}|
let g:Xtest_var += 1{MATCH: *}|
{1:~{MATCH: *}}|
{3:{MATCH: *}}|
Breakpoint in "{MATCH:.*}XdebugBreakExpr.vim" line 1{MATCH: *}|
{MATCH: *}|
]]
screen:expect(initial_screen)
feed(':source %<CR>')
screen:expect([[
Breakpoint in "Foo" line 1{MATCH: *}|
Entering Debug mode. Type "cont" to continue.{MATCH: *}|
Oldval = "10"{MATCH: *}|
Newval = "11"{MATCH: *}|
{MATCH:.*}XdebugBreakExpr.vim{MATCH: *}|
line 1: let g:Xtest_var += 1{MATCH: *}|
{MATCH:.*}XbreakExpr.vim[7]..function Foo{MATCH: *}|
line 1: eval 1{MATCH: *}|
>^{MATCH: *}|
]],
}
]])
feed('cont<CR>')
screen:expect {
grid = [[
^let g:Xtest_var += 1{MATCH: *}|
{1:~{MATCH: *}}|*8
{MATCH: *}|
]],
}
feed(':source %<CR>')
screen:expect {
grid = [[
let g:Xtest_var += 1{MATCH: *}|
{1:~{MATCH: *}}|
{3:{MATCH: *}}|
Breakpoint in "{MATCH:.*}XdebugBreakExpr.vim" line 1{MATCH: *}|
Entering Debug mode. Type "cont" to continue.{MATCH: *}|
screen:expect([[
>cont{MATCH: *}|
Breakpoint in "Foo" line 1{MATCH: *}|
Oldval = "11"{MATCH: *}|
Newval = "12"{MATCH: *}|
{MATCH:.*}XdebugBreakExpr.vim{MATCH: *}|
line 1: let g:Xtest_var += 1{MATCH: *}|
{MATCH:.*}XbreakExpr.vim[9]..function Foo{MATCH: *}|
line 1: eval 1{MATCH: *}|
>^{MATCH: *}|
]],
}
]])
feed('cont<CR>')
screen:expect(initial_screen)
-- Check the behavior without the g: prefix.
-- The Oldval and Newval don't look right here.
command(':breakdel *')
command(':breakadd expr Xtest_var')
feed(':source %<CR>')
screen:expect([[
Breakpoint in "Foo" line 1{MATCH: *}|
Entering Debug mode. Type "cont" to continue.{MATCH: *}|
Oldval = "13"{MATCH: *}|
Newval = "(does not exist)"{MATCH: *}|
{MATCH:.*}XbreakExpr.vim[7]..function Foo{MATCH: *}|
line 1: eval 1{MATCH: *}|
>^{MATCH: *}|
]])
feed('cont<CR>')
screen:expect([[
{MATCH:.*}XbreakExpr.vim[7]..function Foo{MATCH: *}|
line 1: eval 1{MATCH: *}|
>cont{MATCH: *}|
Breakpoint in "Foo" line 2{MATCH: *}|
{MATCH:.*}XbreakExpr.vim[7]..function Foo{MATCH: *}|
line 2: eval 2{MATCH: *}|
>^{MATCH: *}|
]])
feed('cont<CR>')
screen:expect([[
>cont{MATCH: *}|
Breakpoint in "Foo" line 1{MATCH: *}|
Oldval = "14"{MATCH: *}|
Newval = "(does not exist)"{MATCH: *}|
{MATCH:.*}XbreakExpr.vim[9]..function Foo{MATCH: *}|
line 1: eval 1{MATCH: *}|
>^{MATCH: *}|
]])
feed('cont<CR>')
screen:expect([[
{MATCH:.*}XbreakExpr.vim[9]..function Foo{MATCH: *}|
line 1: eval 1{MATCH: *}|
>cont{MATCH: *}|
Breakpoint in "Foo" line 2{MATCH: *}|
{MATCH:.*}XbreakExpr.vim[9]..function Foo{MATCH: *}|
line 2: eval 2{MATCH: *}|
>^{MATCH: *}|
]])
feed('cont<CR>')
screen:expect(initial_screen)
end)
end)