From: Eli Zaretskii Date: Sat, 18 Apr 2020 11:53:13 +0000 (+0300) Subject: Avoid crashes in regex-emacs.c due to GC X-Git-Tag: emacs-27.1-rc1~218 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=f3b62b6c62c41d2e5d15418ea940bce6b11bdf7d;p=emacs.git 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) --- 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. */