patch 9.1.1943: Memory leak with :breakadd expr

Commit: 
https://github.com/vim/vim/commit/a474de64dfd853eb5d3bf04f8bbd6f7d16e10c82
Author: zeertzjq <[email protected]>
Date:   Mon Dec 1 19:43:05 2025 +0000

    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: #18844
    
    Signed-off-by: zeertzjq <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/debugger.c b/src/debugger.c
index 97d54c439..f553a8e6a 100644
--- a/src/debugger.c
+++ b/src/debugger.c
@@ -1111,8 +1111,10 @@ debuggy_find(
            {
                if (bp->dbg_val == NULL)
                {
+                   vim_free(debug_oldval);
                    debug_oldval = typval_tostring(NULL, TRUE);
                    bp->dbg_val = tv;
+                   vim_free(debug_newval);
                    debug_newval = typval_tostring(bp->dbg_val, TRUE);
                    line = TRUE;
                }
@@ -1129,10 +1131,12 @@ debuggy_find(
                        typval_T *v;
 
                        line = TRUE;
+                       vim_free(debug_oldval);
                        debug_oldval = typval_tostring(bp->dbg_val, TRUE);
                        // Need to evaluate again, typval_compare() overwrites
                        // "tv".
                        v = eval_expr_no_emsg(bp);
+                       vim_free(debug_newval);
                        debug_newval = typval_tostring(v, TRUE);
                        free_tv(bp->dbg_val);
                        bp->dbg_val = v;
@@ -1142,7 +1146,9 @@ debuggy_find(
            }
            else if (bp->dbg_val != NULL)
            {
+               vim_free(debug_oldval);
                debug_oldval = typval_tostring(bp->dbg_val, TRUE);
+               vim_free(debug_newval);
                debug_newval = typval_tostring(NULL, TRUE);
                free_tv(bp->dbg_val);
                bp->dbg_val = NULL;
diff --git a/src/testdir/test_debugger.vim b/src/testdir/test_debugger.vim
index 264420998..aa014c434 100644
--- a/src/testdir/test_debugger.vim
+++ b/src/testdir/test_debugger.vim
@@ -361,34 +361,73 @@ func Test_Debugger_breakadd()
 endfunc
 
 " Test for expression breakpoint set using ":breakadd expr <expr>"
+" FIXME: This doesn't seem to work as documented. The breakpoint is not
+" triggered until the next function call.
 func Test_Debugger_breakadd_expr()
   CheckCWD
 
   let lines =<< trim END
+    func Foo()
+      eval 1
+      eval 2
+    endfunc
+
     let g:Xtest_var += 1
+    call Foo()
+    let g:Xtest_var += 1
+    call Foo()
   END
-  call writefile(lines, 'XdebugBreakExpr.vim', 'D')
+  call writefile(lines, 'XbreakExpr.vim', 'D')
 
   " Start Vim in a terminal
-  let buf = RunVimInTerminal('XdebugBreakExpr.vim', {})
+  let buf = RunVimInTerminal('XbreakExpr.vim', {})
   call s:RunDbgCmd(buf, ':let g:Xtest_var = 10')
   call s:RunDbgCmd(buf, ':breakadd expr g:Xtest_var')
-  call s:RunDbgCmd(buf, ':source %')
   let expected =<< trim eval END
     Oldval = "10"
     Newval = "11"
-    {fnamemodify('XdebugBreakExpr.vim', ':p')}
-    line 1: let g:Xtest_var += 1
+    {fnamemodify('XbreakExpr.vim', ':p')}[7]..function Foo
+    line 1: eval 1
   END
   call s:RunDbgCmd(buf, ':source %', expected)
-  call s:RunDbgCmd(buf, 'cont')
   let expected =<< trim eval END
     Oldval = "11"
     Newval = "12"
-    {fnamemodify('XdebugBreakExpr.vim', ':p')}
-    line 1: let g:Xtest_var += 1
+    {fnamemodify('XbreakExpr.vim', ':p')}[9]..function Foo
+    line 1: eval 1
+  END
+  call s:RunDbgCmd(buf, 'cont', expected)
+  call s:RunDbgCmd(buf, 'cont')
+
+  " Check the behavior without the g: prefix.
+  " FIXME: The Oldval and Newval don't look right here.
+  call s:RunDbgCmd(buf, ':breakdel *')
+  call s:RunDbgCmd(buf, ':breakadd expr Xtest_var')
+  let expected =<< trim eval END
+    Oldval = "13"
+    Newval = "(does not exist)"
+    {fnamemodify('XbreakExpr.vim', ':p')}[7]..function Foo
+    line 1: eval 1
   END
   call s:RunDbgCmd(buf, ':source %', expected)
+  let expected =<< trim eval END
+    {fnamemodify('XbreakExpr.vim', ':p')}[7]..function Foo
+    line 2: eval 2
+  END
+  call s:RunDbgCmd(buf, 'cont', expected)
+  let expected =<< trim eval END
+    Oldval = "14"
+    Newval = "(does not exist)"
+    {fnamemodify('XbreakExpr.vim', ':p')}[9]..function Foo
+    line 1: eval 1
+  END
+  call s:RunDbgCmd(buf, 'cont', expected)
+  let expected =<< trim eval END
+    {fnamemodify('XbreakExpr.vim', ':p')}[9]..function Foo
+    line 2: eval 2
+  END
+  call s:RunDbgCmd(buf, 'cont', expected)
+  call s:RunDbgCmd(buf, 'cont')
 
   call StopVimInTerminal(buf)
 endfunc
diff --git a/src/version.c b/src/version.c
index 81e8cf3b7..d347aac56 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1943,
 /**/
     1942,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1vQA44-00BcwZ-S3%40256bit.org.

Raspunde prin e-mail lui