diff options
author | Eli Zaretskii <eliz@gnu.org> | 2020-04-18 14:53:13 +0300 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2020-04-18 14:53:13 +0300 |
commit | f3b62b6c62c41d2e5d15418ea940bce6b11bdf7d (patch) | |
tree | 7a80aedb7cb33ea4d2ff172abfba677aea47ff27 | |
parent | 175c61c18bfaa1d75aa087ba4bd4de3ebfe1a1d6 (diff) | |
download | emacs-f3b62b6c62c41d2e5d15418ea940bce6b11bdf7d.tar.gz emacs-f3b62b6c62c41d2e5d15418ea940bce6b11bdf7d.tar.bz2 emacs-f3b62b6c62c41d2e5d15418ea940bce6b11bdf7d.zip |
Avoid crashes in regex-emacs.c due to GC
* src/regex-emacs.c (re_match_2_internal): Prevent GC from
invalidating C pointers to buffer text. (Bug#40661)
-rw-r--r-- | src/regex-emacs.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/src/regex-emacs.c b/src/regex-emacs.c index 694431c95e2..f456b495397 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c @@ -3853,6 +3853,12 @@ re_match_2 (struct re_pattern_buffer *bufp, return result; } +static void +unwind_re_match (void *ptr) +{ + struct buffer *b = (struct buffer *) ptr; + b->text->inhibit_shrinking = 0; +} /* This is a separate function so that we can force an alloca cleanup afterwards. */ @@ -3949,6 +3955,19 @@ re_match_2_internal (struct re_pattern_buffer *bufp, INIT_FAIL_STACK (); + ptrdiff_t count = SPECPDL_INDEX (); + + /* Prevent shrinking and relocation of buffer text if GC happens + while we are inside this function. The calls to + UPDATE_SYNTAX_TABLE_* macros can trigger GC if they call Lisp, + and we have C pointers to buffer text that must not become + invalid as result of GC. */ + if (!current_buffer->text->inhibit_shrinking) + { + record_unwind_protect_ptr (unwind_re_match, current_buffer); + current_buffer->text->inhibit_shrinking = 1; + } + /* Do not bother to initialize all the register variables if there are no groups in the pattern, as it takes a fair amount of time. If there are groups, we include space for register 0 (the whole @@ -3965,6 +3984,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, /* The starting position is bogus. */ if (pos < 0 || pos > size1 + size2) { + unbind_to (count, Qnil); SAFE_FREE (); return -1; } @@ -4179,6 +4199,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, DEBUG_PRINT ("Returning %td from re_match_2.\n", dcnt); + unbind_to (count, Qnil); SAFE_FREE (); return dcnt; } @@ -5025,6 +5046,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, if (best_regs_set) goto restore_best_regs; + unbind_to (count, Qnil); SAFE_FREE (); return -1; /* Failure to match. */ |