changeset 33431:af2b017a5a7a stable

Fix segmentation fault when trying to set breakpoint in non-existent method (bug #65610). * libinterp/parse-tree/pt-eval.cc (tree_evaluator::get_user_code): Check if classdef method with given name exists before trying to dereference representation. * test/classdef-debug/test_classdef_breakpints.tst: Add tests for setting breakpoints using method names. * etc/NEWS.9.md: Add note.
author Markus Mützel <markus.muetzel@gmx.de>
date Thu, 18 Apr 2024 20:59:19 +0200
parents df60dee3a901
children 83352d86f20d 27e915d3a79c
files etc/NEWS.9.md libinterp/parse-tree/pt-eval.cc test/classdef-debug/test_classdef_breakpoints.tst
diffstat 3 files changed, 58 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS.9.md	Thu Apr 18 18:29:17 2024 +0200
+++ b/etc/NEWS.9.md	Thu Apr 18 20:59:19 2024 +0200
@@ -17,6 +17,8 @@
 - Correctly scale figure position on screen with DPI scaling (high DPI).
 - `profile ('on')` now clears any existing profile data as the documentation
   states (bug #65595).
+- Fix segmentation fault when trying to set breakpoint in non-existent method
+  of `classdef` class (bug #65610).
 
 ### GUI
 
--- a/libinterp/parse-tree/pt-eval.cc	Thu Apr 18 18:29:17 2024 +0200
+++ b/libinterp/parse-tree/pt-eval.cc	Thu Apr 18 20:59:19 2024 +0200
@@ -2989,7 +2989,13 @@
 
           cdef_class cls = cdm.find_class (dispatch_type, false);
           if (cls.ok () && cls.get_name () == dispatch_type)
-            fcn = cls.find_method (method).get_function ();
+            {
+              cdef_method meth = cls.find_method (method);
+              if (meth.ok () && meth.get_name () == method)
+                fcn = meth.get_function ();
+              else
+                return nullptr;
+            }
 
           // If there is no classdef method, then try legacy classes.
           if (fcn.is_undefined ())
--- a/test/classdef-debug/test_classdef_breakpoints.tst	Thu Apr 18 18:29:17 2024 +0200
+++ b/test/classdef-debug/test_classdef_breakpoints.tst	Thu Apr 18 20:59:19 2024 +0200
@@ -1,4 +1,5 @@
-##  Test script for setting breakpoints in classdefs using line numbers.
+##  Test script for setting breakpoints in classdefs
+##  using line numbers or method names.
 
 %!function assert_dbstatus (bp0)
 %!  dbs = dbstatus ();
@@ -10,6 +11,7 @@
 %!  endif
 %!endfunction
 
+## Set breakpoints by line numbers
 %!test <*46451>
 %! if (isguirunning ())
 %!   orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file",
@@ -33,6 +35,51 @@
 %!   endif
 %! end_unwind_protect
 
+## Set breakpoints by method name
+%!test
+%! if (isguirunning ())
+%!   orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file",
+%!                                                     "false");
+%! endif
+%! unwind_protect
+%!   ## Add breakpoint in constructor
+%!   dbstop @classdef_breakpoints/classdef_breakpoints;
+%!   assert_dbstatus ([7]);
+%!
+%!   ## Add breakpoints in methods.
+%!   dbstop @classdef_breakpoints/foo;
+%!   dbstop @classdef_breakpoints/bar;
+%!   assert_dbstatus ([7, 10, 13]);
+%!
+%!   ## Remove breakpoint from one method.
+%!   dbclear @classdef_breakpoints/foo;
+%!   assert_dbstatus ([7, 13]);
+%!
+%!   ## Clear all breakpoints, none should be left.
+%!   dbclear classdef_breakpoints;
+%!   assert_dbstatus ([]);
+%! unwind_protect_cleanup
+%!   if (isguirunning ())
+%!     __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg);
+%!   endif
+%! end_unwind_protect
+
+## Try to add breakpoint in non-existent method
+%!test <65610>
+%! if (isguirunning ())
+%!   orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file",
+%!                                                     "false");
+%! endif
+%! unwind_protect
+%!   ## This should error.  But it does not.
+%!   fail ("dbstop @classdef_breakpoints/baz;", "unable to find function");
+%! unwind_protect_cleanup
+%!   dbclear classdef_breakpoints;
+%!   if (isguirunning ())
+%!     __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg);
+%!   endif
+%! end_unwind_protect
+
 %!test <46451>
 %! if (isguirunning ())
 %!   orig_show_dbg = __event_manager_gui_preference__ ("editor/show_dbg_file",
@@ -41,7 +88,7 @@
 %! unwind_protect
 %!   ## Add breakpoint in local function.
 %!   dbstop classdef_breakpoints 19;
-%!   assert_dbstatus ([7, 13, 20]);
+%!   assert_dbstatus ([20]);
 %! unwind_protect_cleanup
 %!   if (isguirunning ())
 %!     __event_manager_gui_preference__ ("editor/show_dbg_file", orig_show_dbg);