diff options
| author | Eli Zaretskii | 2020-04-18 14:53:13 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2020-04-18 14:53:13 +0300 |
| commit | f3b62b6c62c41d2e5d15418ea940bce6b11bdf7d (patch) | |
| tree | 7a80aedb7cb33ea4d2ff172abfba677aea47ff27 | |
| parent | 175c61c18bfaa1d75aa087ba4bd4de3ebfe1a1d6 (diff) | |
| download | emacs-f3b62b6c62c41d2e5d15418ea940bce6b11bdf7d.tar.gz 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, | |||
| 3853 | return result; | 3853 | return result; |
| 3854 | } | 3854 | } |
| 3855 | 3855 | ||
| 3856 | static void | ||
| 3857 | unwind_re_match (void *ptr) | ||
| 3858 | { | ||
| 3859 | struct buffer *b = (struct buffer *) ptr; | ||
| 3860 | b->text->inhibit_shrinking = 0; | ||
| 3861 | } | ||
| 3856 | 3862 | ||
| 3857 | /* This is a separate function so that we can force an alloca cleanup | 3863 | /* This is a separate function so that we can force an alloca cleanup |
| 3858 | afterwards. */ | 3864 | afterwards. */ |
| @@ -3949,6 +3955,19 @@ re_match_2_internal (struct re_pattern_buffer *bufp, | |||
| 3949 | 3955 | ||
| 3950 | INIT_FAIL_STACK (); | 3956 | INIT_FAIL_STACK (); |
| 3951 | 3957 | ||
| 3958 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 3959 | |||
| 3960 | /* Prevent shrinking and relocation of buffer text if GC happens | ||
| 3961 | while we are inside this function. The calls to | ||
| 3962 | UPDATE_SYNTAX_TABLE_* macros can trigger GC if they call Lisp, | ||
| 3963 | and we have C pointers to buffer text that must not become | ||
| 3964 | invalid as result of GC. */ | ||
| 3965 | if (!current_buffer->text->inhibit_shrinking) | ||
| 3966 | { | ||
| 3967 | record_unwind_protect_ptr (unwind_re_match, current_buffer); | ||
| 3968 | current_buffer->text->inhibit_shrinking = 1; | ||
| 3969 | } | ||
| 3970 | |||
| 3952 | /* Do not bother to initialize all the register variables if there are | 3971 | /* Do not bother to initialize all the register variables if there are |
| 3953 | no groups in the pattern, as it takes a fair amount of time. If | 3972 | no groups in the pattern, as it takes a fair amount of time. If |
| 3954 | there are groups, we include space for register 0 (the whole | 3973 | there are groups, we include space for register 0 (the whole |
| @@ -3965,6 +3984,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, | |||
| 3965 | /* The starting position is bogus. */ | 3984 | /* The starting position is bogus. */ |
| 3966 | if (pos < 0 || pos > size1 + size2) | 3985 | if (pos < 0 || pos > size1 + size2) |
| 3967 | { | 3986 | { |
| 3987 | unbind_to (count, Qnil); | ||
| 3968 | SAFE_FREE (); | 3988 | SAFE_FREE (); |
| 3969 | return -1; | 3989 | return -1; |
| 3970 | } | 3990 | } |
| @@ -4179,6 +4199,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, | |||
| 4179 | 4199 | ||
| 4180 | DEBUG_PRINT ("Returning %td from re_match_2.\n", dcnt); | 4200 | DEBUG_PRINT ("Returning %td from re_match_2.\n", dcnt); |
| 4181 | 4201 | ||
| 4202 | unbind_to (count, Qnil); | ||
| 4182 | SAFE_FREE (); | 4203 | SAFE_FREE (); |
| 4183 | return dcnt; | 4204 | return dcnt; |
| 4184 | } | 4205 | } |
| @@ -5025,6 +5046,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, | |||
| 5025 | if (best_regs_set) | 5046 | if (best_regs_set) |
| 5026 | goto restore_best_regs; | 5047 | goto restore_best_regs; |
| 5027 | 5048 | ||
| 5049 | unbind_to (count, Qnil); | ||
| 5028 | SAFE_FREE (); | 5050 | SAFE_FREE (); |
| 5029 | 5051 | ||
| 5030 | return -1; /* Failure to match. */ | 5052 | return -1; /* Failure to match. */ |