]> git.eshelyaron.com Git - emacs.git/commitdiff
Check for buffer liveness when accessing tree-sitter node (bug#71012)
authorYuan Fu <casouri@gmail.com>
Sat, 1 Jun 2024 17:20:48 +0000 (10:20 -0700)
committerEshel Yaron <me@eshelyaron.com>
Sat, 8 Jun 2024 12:58:42 +0000 (14:58 +0200)
* 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.

(cherry picked from commit 20af58d3a13ddb5c2ca376da8cdd3fde4833ca2d)

src/print.c
src/treesit.c
src/treesit.h

index 7aacd2b2e906c79882e5a6a347ce707b8fc5a1e5..6a27ceac5f0bd9f198127bbb9561aa5c42f8ad0f 100644 (file)
@@ -2033,6 +2033,11 @@ print_vectorlike_unreadable (Lisp_Object obj, Lisp_Object printcharfun,
          print_c_string ("-outdated>", printcharfun);
          return;
        }
+      if (!treesit_node_buffer_live_p (obj))
+       {
+         print_c_string ("-in-killed-buffer>", printcharfun);
+         break;
+       }
       printchar (' ', printcharfun);
       /* Now the node must be up-to-date, and calling functions like
         Ftreesit_node_start will not signal.  */
index d86ab5011873ab9e0505e18ab897ccdb2f0ee00e..9f0eb061056495003408d9ea230c7c285f223b07 100644 (file)
@@ -1837,6 +1837,13 @@ treesit_check_node (Lisp_Object obj)
   CHECK_TS_NODE (obj);
   if (!treesit_node_uptodate_p (obj))
     xsignal1 (Qtreesit_node_outdated, obj);
+
+  /* Technically a lot of node functions can work without the
+     associated buffer being alive, but I doubt there're any real
+     use-cases for that; OTOH putting the buffer-liveness check here is
+     simple, clean, and safe.  */
+  if (!treesit_node_buffer_live_p (obj))
+    xsignal1 (Qtreesit_node_buffer_killed, obj);
 }
 
 /* Checks that OBJ is a positive integer and it is within the visible
@@ -1857,6 +1864,14 @@ treesit_node_uptodate_p (Lisp_Object obj)
   return XTS_NODE (obj)->timestamp == XTS_PARSER (lisp_parser)->timestamp;
 }
 
+bool
+treesit_node_buffer_live_p (Lisp_Object obj)
+{
+  struct buffer *buffer
+    = XBUFFER (XTS_PARSER (XTS_NODE (obj)->parser)->buffer);
+  return BUFFER_LIVE_P (buffer);
+}
+
 DEFUN ("treesit-node-type",
        Ftreesit_node_type, Streesit_node_type, 1, 1, 0,
        doc: /* Return the NODE's type as a string.
@@ -4016,6 +4031,8 @@ syms_of_treesit (void)
          "treesit-load-language-error");
   DEFSYM (Qtreesit_node_outdated,
          "treesit-node-outdated");
+  DEFSYM (Qtreesit_node_buffer_killed,
+         "treesit-node-buffer-killed");
   DEFSYM (Quser_emacs_directory,
          "user-emacs-directory");
   DEFSYM (Qtreesit_parser_deleted, "treesit-parser-deleted");
@@ -4046,6 +4063,9 @@ syms_of_treesit (void)
   define_error (Qtreesit_node_outdated,
                "This node is outdated, please retrieve a new one",
                Qtreesit_error);
+  define_error (Qtreesit_node_buffer_killed,
+               "The buffer associated with this node is killed",
+               Qtreesit_error);
   define_error (Qtreesit_parser_deleted,
                "This parser is deleted and cannot be used",
                Qtreesit_error);
index bb81bf0e2b3854daaa5abf18edcaf078d14faaec..d3c6aa4c250dad7173d64a981282d6a7dfb66964 100644 (file)
@@ -194,6 +194,7 @@ extern Lisp_Object make_treesit_parser (Lisp_Object, TSParser *, TSTree *,
 extern Lisp_Object make_treesit_node (Lisp_Object, TSNode);
 
 extern bool treesit_node_uptodate_p (Lisp_Object);
+extern bool treesit_node_buffer_live_p (Lisp_Object);
 
 extern void treesit_delete_parser (struct Lisp_TS_Parser *);
 extern void treesit_delete_query (struct Lisp_TS_Query *);