aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuan Fu2024-06-01 10:20:48 -0700
committerYuan Fu2024-06-01 10:29:55 -0700
commit20af58d3a13ddb5c2ca376da8cdd3fde4833ca2d (patch)
tree34911232c2aa99244baef21db031ee6a8b326e30
parentbf50aa38f9d2a3a5af8d32ce139c7533c912c476 (diff)
downloademacs-20af58d3a13ddb5c2ca376da8cdd3fde4833ca2d.tar.gz
emacs-20af58d3a13ddb5c2ca376da8cdd3fde4833ca2d.zip
Check for buffer liveness when accessing tree-sitter node (bug#71012)
* src/treesit.h (treesit_node_buffer_live_p): Declare function. * src/print.c (print_vectorlike): Print node without position if buffer is killed. * src/treesit.c (treesit_node_buffer_live_p): New function. (treesit_check_node): Add buffer liveness check. (syms_of_treesit): New error treesit-node-buffer-killed.
-rw-r--r--src/print.c5
-rw-r--r--src/treesit.c20
-rw-r--r--src/treesit.h1
3 files changed, 26 insertions, 0 deletions
diff --git a/src/print.c b/src/print.c
index d52d98ad371..8ee5a3616eb 100644
--- a/src/print.c
+++ b/src/print.c
@@ -2029,6 +2029,11 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
2029 print_c_string ("-outdated>", printcharfun); 2029 print_c_string ("-outdated>", printcharfun);
2030 break; 2030 break;
2031 } 2031 }
2032 if (!treesit_node_buffer_live_p (obj))
2033 {
2034 print_c_string ("-in-killed-buffer>", printcharfun);
2035 break;
2036 }
2032 printchar (' ', printcharfun); 2037 printchar (' ', printcharfun);
2033 /* Now the node must be up-to-date, and calling functions like 2038 /* Now the node must be up-to-date, and calling functions like
2034 Ftreesit_node_start will not signal. */ 2039 Ftreesit_node_start will not signal. */
diff --git a/src/treesit.c b/src/treesit.c
index 21c61a35e70..45efa429f9a 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -1786,6 +1786,13 @@ treesit_check_node (Lisp_Object obj)
1786 CHECK_TS_NODE (obj); 1786 CHECK_TS_NODE (obj);
1787 if (!treesit_node_uptodate_p (obj)) 1787 if (!treesit_node_uptodate_p (obj))
1788 xsignal1 (Qtreesit_node_outdated, obj); 1788 xsignal1 (Qtreesit_node_outdated, obj);
1789
1790 /* Technically a lot of node functions can work without the
1791 associated buffer being alive, but I doubt there're any real
1792 use-cases for that; OTOH putting the buffer-liveness check here is
1793 simple, clean, and safe. */
1794 if (!treesit_node_buffer_live_p (obj))
1795 xsignal1 (Qtreesit_node_buffer_killed, obj);
1789} 1796}
1790 1797
1791/* Checks that OBJ is a positive integer and it is within the visible 1798/* Checks that OBJ is a positive integer and it is within the visible
@@ -1806,6 +1813,14 @@ treesit_node_uptodate_p (Lisp_Object obj)
1806 return XTS_NODE (obj)->timestamp == XTS_PARSER (lisp_parser)->timestamp; 1813 return XTS_NODE (obj)->timestamp == XTS_PARSER (lisp_parser)->timestamp;
1807} 1814}
1808 1815
1816bool
1817treesit_node_buffer_live_p (Lisp_Object obj)
1818{
1819 struct buffer *buffer
1820 = XBUFFER (XTS_PARSER (XTS_NODE (obj)->parser)->buffer);
1821 return BUFFER_LIVE_P (buffer);
1822}
1823
1809DEFUN ("treesit-node-type", 1824DEFUN ("treesit-node-type",
1810 Ftreesit_node_type, Streesit_node_type, 1, 1, 0, 1825 Ftreesit_node_type, Streesit_node_type, 1, 1, 0,
1811 doc: /* Return the NODE's type as a string. 1826 doc: /* Return the NODE's type as a string.
@@ -3549,6 +3564,8 @@ syms_of_treesit (void)
3549 "treesit-load-language-error"); 3564 "treesit-load-language-error");
3550 DEFSYM (Qtreesit_node_outdated, 3565 DEFSYM (Qtreesit_node_outdated,
3551 "treesit-node-outdated"); 3566 "treesit-node-outdated");
3567 DEFSYM (Qtreesit_node_buffer_killed,
3568 "treesit-node-buffer-killed");
3552 DEFSYM (Quser_emacs_directory, 3569 DEFSYM (Quser_emacs_directory,
3553 "user-emacs-directory"); 3570 "user-emacs-directory");
3554 DEFSYM (Qtreesit_parser_deleted, "treesit-parser-deleted"); 3571 DEFSYM (Qtreesit_parser_deleted, "treesit-parser-deleted");
@@ -3577,6 +3594,9 @@ syms_of_treesit (void)
3577 define_error (Qtreesit_node_outdated, 3594 define_error (Qtreesit_node_outdated,
3578 "This node is outdated, please retrieve a new one", 3595 "This node is outdated, please retrieve a new one",
3579 Qtreesit_error); 3596 Qtreesit_error);
3597 define_error (Qtreesit_node_buffer_killed,
3598 "The buffer associated with this node is killed",
3599 Qtreesit_error);
3580 define_error (Qtreesit_parser_deleted, 3600 define_error (Qtreesit_parser_deleted,
3581 "This parser is deleted and cannot be used", 3601 "This parser is deleted and cannot be used",
3582 Qtreesit_error); 3602 Qtreesit_error);
diff --git a/src/treesit.h b/src/treesit.h
index f5c8c67395d..dcb19648a37 100644
--- a/src/treesit.h
+++ b/src/treesit.h
@@ -189,6 +189,7 @@ extern Lisp_Object make_treesit_parser (Lisp_Object, TSParser *, TSTree *,
189extern Lisp_Object make_treesit_node (Lisp_Object, TSNode); 189extern Lisp_Object make_treesit_node (Lisp_Object, TSNode);
190 190
191extern bool treesit_node_uptodate_p (Lisp_Object); 191extern bool treesit_node_uptodate_p (Lisp_Object);
192extern bool treesit_node_buffer_live_p (Lisp_Object);
192 193
193extern void treesit_delete_parser (struct Lisp_TS_Parser *); 194extern void treesit_delete_parser (struct Lisp_TS_Parser *);
194extern void treesit_delete_query (struct Lisp_TS_Query *); 195extern void treesit_delete_query (struct Lisp_TS_Query *);