From 7973227f67cd8ea4a1ed590ebc279b34ece86c12 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 22 Sep 2021 10:07:25 +0300 Subject: [PATCH] Update comments warning about GC-resistant C programming * src/eval.c: Remove an outdated comment about protection from GC. * src/buffer.h: * src/lisp.h: Add warnings about using 'char *' pointers to text of Lisp strings and buffer text in code that could GC. Reported by Po Lu --- src/buffer.h | 11 +++++++++++ src/eval.c | 3 --- src/lisp.h | 8 ++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/buffer.h b/src/buffer.h index 24e9c3fcbc8..8623bed08e6 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -60,6 +60,14 @@ enum { BEG = 1, BEG_BYTE = BEG }; /* Macros for the addresses of places in the buffer. */ +/* WARNING: Use the 'char *' pointers to buffer text with care in code + that could GC: GC can relocate buffer text, invalidating such + pointers. It is best to use character or byte position instead, + delaying the access through BYTE_POS_ADDR etc. pointers to the + latest possible moment. If you must use the 'char *' pointers + (e.g., for speed), be sure to adjust them after any call that could + potentially GC. */ + /* Address of beginning of buffer. */ #define BEG_ADDR (current_buffer->text->beg) @@ -1002,6 +1010,9 @@ SET_BUF_PT_BOTH (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t byte) or convert between a byte position and an address. These functions do not check that the position is in range. */ +/* See the important WARNING above about using the 'char *' pointers + returned by these functions. */ + /* Return the address of byte position N in current buffer. */ INLINE unsigned char * diff --git a/src/eval.c b/src/eval.c index 76fe671b6dd..2bb7cfe6002 100644 --- a/src/eval.c +++ b/src/eval.c @@ -364,9 +364,6 @@ do_debug_on_call (Lisp_Object code, ptrdiff_t count) call_debugger (list1 (code)); } -/* NOTE!!! Every function that can call EVAL must protect its args - and temporaries from garbage collection while it needs them. - The definition of `For' shows what you have to do. */ DEFUN ("or", For, Sor, 0, UNEVALLED, 0, doc: /* Eval args until one of them yields non-nil, then return that value. diff --git a/src/lisp.h b/src/lisp.h index 720e621d19c..09e0b8e9bda 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1555,6 +1555,14 @@ STRING_MULTIBYTE (Lisp_Object str) /* Convenience functions for dealing with Lisp strings. */ +/* WARNING: Use the 'char *' pointers to string data with care in code + that could GC: GC can relocate string data, invalidating such + pointers. It is best to use string character or byte index + instead, delaying the access through SDATA/SSDATA pointers to the + latest possible moment. If you must use the 'char *' pointers + (e.g., for speed), be sure to adjust them after any call that could + potentially GC. */ + INLINE unsigned char * SDATA (Lisp_Object string) { -- 2.39.5