aboutsummaryrefslogtreecommitdiffstats
path: root/src/treesit.c
diff options
context:
space:
mode:
authorYuan Fu2023-04-13 14:36:46 -0700
committerEli Zaretskii2023-04-14 09:07:46 +0300
commit759cdf1e510d9e0689aefeced784fbb81644cd5e (patch)
tree37650afd6e0fa8819332da1d83fa8cdbbaa86454 /src/treesit.c
parent864a4dc236395e441aafd23b9cbca099afdc5324 (diff)
downloademacs-759cdf1e510d9e0689aefeced784fbb81644cd5e.tar.gz
emacs-759cdf1e510d9e0689aefeced784fbb81644cd5e.zip
Catch signals produced by PRED in tree-sitter search functions
Earlier we switched to using cursors rather than nodes to traverse the parse tree. Because cursors need cleanup, we have to catch signals thrown by the predicate functions and free the cursor. Failing to do this will result in leaking the cursor whenever the predicate function signals in a search function. This change fixes the leak. * src/treesit.c (treesit_traverse_cleanup_cursor): New function. (Ftreesit_search_subtree) (Ftreesit_search_forward) (Ftreesit_induce_sparse_tree): Catch signals. (Bug#62823) (cherry picked from commit a5eb9f6ad4e6f5a2819b540a477f1e889f6ef355)
Diffstat (limited to 'src/treesit.c')
-rw-r--r--src/treesit.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/treesit.c b/src/treesit.c
index 1bb52888f4b..7d5d033c02c 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -3156,6 +3156,12 @@ treesit_search_forward (TSTreeCursor *cursor,
3156 } 3156 }
3157} 3157}
3158 3158
3159/** Cleanup function for cursor. */
3160static void treesit_traverse_cleanup_cursor(void *cursor)
3161{
3162 ts_tree_cursor_delete ((TSTreeCursor *) cursor);
3163}
3164
3159DEFUN ("treesit-search-subtree", 3165DEFUN ("treesit-search-subtree",
3160 Ftreesit_search_subtree, 3166 Ftreesit_search_subtree,
3161 Streesit_search_subtree, 2, 5, 0, 3167 Streesit_search_subtree, 2, 5, 0,
@@ -3197,12 +3203,18 @@ Return the first matched node, or nil if none matches. */)
3197 if (!treesit_cursor_helper (&cursor, XTS_NODE (node)->node, parser)) 3203 if (!treesit_cursor_helper (&cursor, XTS_NODE (node)->node, parser))
3198 return return_value; 3204 return return_value;
3199 3205
3206 specpdl_ref count = SPECPDL_INDEX ();
3207 record_unwind_protect_ptr (treesit_traverse_cleanup_cursor, &cursor);
3208
3200 if (treesit_search_dfs (&cursor, predicate, parser, NILP (backward), 3209 if (treesit_search_dfs (&cursor, predicate, parser, NILP (backward),
3201 NILP (all), the_limit, false)) 3210 NILP (all), the_limit, false))
3202 { 3211 {
3203 TSNode node = ts_tree_cursor_current_node (&cursor); 3212 TSNode node = ts_tree_cursor_current_node (&cursor);
3204 return_value = make_treesit_node (parser, node); 3213 return_value = make_treesit_node (parser, node);
3205 } 3214 }
3215
3216 unbind_to (count, Qnil);
3217
3206 ts_tree_cursor_delete (&cursor); 3218 ts_tree_cursor_delete (&cursor);
3207 return return_value; 3219 return return_value;
3208} 3220}
@@ -3254,12 +3266,18 @@ always traverse leaf nodes first, then upwards. */)
3254 if (!treesit_cursor_helper (&cursor, XTS_NODE (start)->node, parser)) 3266 if (!treesit_cursor_helper (&cursor, XTS_NODE (start)->node, parser))
3255 return return_value; 3267 return return_value;
3256 3268
3269 specpdl_ref count = SPECPDL_INDEX ();
3270 record_unwind_protect_ptr (treesit_traverse_cleanup_cursor, &cursor);
3271
3257 if (treesit_search_forward (&cursor, predicate, parser, 3272 if (treesit_search_forward (&cursor, predicate, parser,
3258 NILP (backward), NILP (all))) 3273 NILP (backward), NILP (all)))
3259 { 3274 {
3260 TSNode node = ts_tree_cursor_current_node (&cursor); 3275 TSNode node = ts_tree_cursor_current_node (&cursor);
3261 return_value = make_treesit_node (parser, node); 3276 return_value = make_treesit_node (parser, node);
3262 } 3277 }
3278
3279 unbind_to (count, Qnil);
3280
3263 ts_tree_cursor_delete (&cursor); 3281 ts_tree_cursor_delete (&cursor);
3264 return return_value; 3282 return return_value;
3265} 3283}
@@ -3376,8 +3394,14 @@ a regexp. */)
3376 to use treesit_cursor_helper. */ 3394 to use treesit_cursor_helper. */
3377 TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (root)->node); 3395 TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (root)->node);
3378 3396
3397 specpdl_ref count = SPECPDL_INDEX ();
3398 record_unwind_protect_ptr (treesit_traverse_cleanup_cursor, &cursor);
3399
3379 treesit_build_sparse_tree (&cursor, parent, predicate, process_fn, 3400 treesit_build_sparse_tree (&cursor, parent, predicate, process_fn,
3380 the_limit, parser); 3401 the_limit, parser);
3402
3403 unbind_to (count, Qnil);
3404
3381 ts_tree_cursor_delete (&cursor); 3405 ts_tree_cursor_delete (&cursor);
3382 Fsetcdr (parent, Fnreverse (Fcdr (parent))); 3406 Fsetcdr (parent, Fnreverse (Fcdr (parent)));
3383 if (NILP (Fcdr (parent))) 3407 if (NILP (Fcdr (parent)))