aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYuan Fu2023-04-13 14:36:46 -0700
committerYuan Fu2023-04-13 15:08:51 -0700
commita5eb9f6ad4e6f5a2819b540a477f1e889f6ef355 (patch)
tree6f13df041b5e51f552ce438338ff887c2ba21029 /src
parentdff254946a72db1d592e6e2f71f85786e5e5bdec (diff)
downloademacs-a5eb9f6ad4e6f5a2819b540a477f1e889f6ef355.tar.gz
emacs-a5eb9f6ad4e6f5a2819b540a477f1e889f6ef355.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.
Diffstat (limited to 'src')
-rw-r--r--src/treesit.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/treesit.c b/src/treesit.c
index fd5fda78133..76d1dc8ccf4 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -3247,6 +3247,12 @@ treesit_search_forward (TSTreeCursor *cursor,
3247 } 3247 }
3248} 3248}
3249 3249
3250/** Cleanup function for cursor. */
3251static void treesit_traverse_cleanup_cursor(void *cursor)
3252{
3253 ts_tree_cursor_delete ((TSTreeCursor *) cursor);
3254}
3255
3250DEFUN ("treesit-search-subtree", 3256DEFUN ("treesit-search-subtree",
3251 Ftreesit_search_subtree, 3257 Ftreesit_search_subtree,
3252 Streesit_search_subtree, 2, 5, 0, 3258 Streesit_search_subtree, 2, 5, 0,
@@ -3288,12 +3294,18 @@ Return the first matched node, or nil if none matches. */)
3288 if (!treesit_cursor_helper (&cursor, XTS_NODE (node)->node, parser)) 3294 if (!treesit_cursor_helper (&cursor, XTS_NODE (node)->node, parser))
3289 return return_value; 3295 return return_value;
3290 3296
3297 specpdl_ref count = SPECPDL_INDEX ();
3298 record_unwind_protect_ptr (treesit_traverse_cleanup_cursor, &cursor);
3299
3291 if (treesit_search_dfs (&cursor, predicate, parser, NILP (backward), 3300 if (treesit_search_dfs (&cursor, predicate, parser, NILP (backward),
3292 NILP (all), the_limit, false)) 3301 NILP (all), the_limit, false))
3293 { 3302 {
3294 TSNode node = ts_tree_cursor_current_node (&cursor); 3303 TSNode node = ts_tree_cursor_current_node (&cursor);
3295 return_value = make_treesit_node (parser, node); 3304 return_value = make_treesit_node (parser, node);
3296 } 3305 }
3306
3307 unbind_to (count, Qnil);
3308
3297 ts_tree_cursor_delete (&cursor); 3309 ts_tree_cursor_delete (&cursor);
3298 return return_value; 3310 return return_value;
3299} 3311}
@@ -3345,12 +3357,18 @@ always traverse leaf nodes first, then upwards. */)
3345 if (!treesit_cursor_helper (&cursor, XTS_NODE (start)->node, parser)) 3357 if (!treesit_cursor_helper (&cursor, XTS_NODE (start)->node, parser))
3346 return return_value; 3358 return return_value;
3347 3359
3360 specpdl_ref count = SPECPDL_INDEX ();
3361 record_unwind_protect_ptr (treesit_traverse_cleanup_cursor, &cursor);
3362
3348 if (treesit_search_forward (&cursor, predicate, parser, 3363 if (treesit_search_forward (&cursor, predicate, parser,
3349 NILP (backward), NILP (all))) 3364 NILP (backward), NILP (all)))
3350 { 3365 {
3351 TSNode node = ts_tree_cursor_current_node (&cursor); 3366 TSNode node = ts_tree_cursor_current_node (&cursor);
3352 return_value = make_treesit_node (parser, node); 3367 return_value = make_treesit_node (parser, node);
3353 } 3368 }
3369
3370 unbind_to (count, Qnil);
3371
3354 ts_tree_cursor_delete (&cursor); 3372 ts_tree_cursor_delete (&cursor);
3355 return return_value; 3373 return return_value;
3356} 3374}
@@ -3467,8 +3485,14 @@ a regexp. */)
3467 to use treesit_cursor_helper. */ 3485 to use treesit_cursor_helper. */
3468 TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (root)->node); 3486 TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (root)->node);
3469 3487
3488 specpdl_ref count = SPECPDL_INDEX ();
3489 record_unwind_protect_ptr (treesit_traverse_cleanup_cursor, &cursor);
3490
3470 treesit_build_sparse_tree (&cursor, parent, predicate, process_fn, 3491 treesit_build_sparse_tree (&cursor, parent, predicate, process_fn,
3471 the_limit, parser); 3492 the_limit, parser);
3493
3494 unbind_to (count, Qnil);
3495
3472 ts_tree_cursor_delete (&cursor); 3496 ts_tree_cursor_delete (&cursor);
3473 Fsetcdr (parent, Fnreverse (Fcdr (parent))); 3497 Fsetcdr (parent, Fnreverse (Fcdr (parent)));
3474 if (NILP (Fcdr (parent))) 3498 if (NILP (Fcdr (parent)))