diff options
| author | Paul Eggert | 2012-02-25 11:39:42 -0800 |
|---|---|---|
| committer | Paul Eggert | 2012-02-25 11:39:42 -0800 |
| commit | 27f3c6378b0e09d6e3c1b4b55b7e2fc5c22c8e65 (patch) | |
| tree | 2e47f4531248214cbb4bd6ceb3bb152741e96aff /src | |
| parent | 23453255524411eaae5c79d7e4ae6c22f6f05f3f (diff) | |
| download | emacs-27f3c6378b0e09d6e3c1b4b55b7e2fc5c22c8e65.tar.gz emacs-27f3c6378b0e09d6e3c1b4b55b7e2fc5c22c8e65.zip | |
Generalize fix for crash due to non-contiguous EMACS_INT (Bug#10780).
Suggested by Stefan Monnier in
<http://lists.gnu.org/archive/html/emacs-devel/2012-02/msg00692.html>.
* alloc.c (widen_to_Lisp_Object): New static function.
(mark_memory): Also mark Lisp_Objects by fetching pointer words
and widening them to Lisp_Objects. This would work even if
USE_LSB_TAG is defined and wide integers are used, which might
happen in a future version of Emacs.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/alloc.c | 27 | ||||
| -rw-r--r-- | src/lisp.h | 18 |
3 files changed, 39 insertions, 17 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 1566d6258af..9221041da52 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2012-02-25 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Generalize fix for crash due to non-contiguous EMACS_INT (Bug#10780). | ||
| 4 | Suggested by Stefan Monnier in | ||
| 5 | <http://lists.gnu.org/archive/html/emacs-devel/2012-02/msg00692.html>. | ||
| 6 | * alloc.c (widen_to_Lisp_Object): New static function. | ||
| 7 | (mark_memory): Also mark Lisp_Objects by fetching pointer words | ||
| 8 | and widening them to Lisp_Objects. This would work even if | ||
| 9 | USE_LSB_TAG is defined and wide integers are used, which might | ||
| 10 | happen in a future version of Emacs. | ||
| 11 | |||
| 1 | 2012-02-25 Chong Yidong <cyd@gnu.org> | 12 | 2012-02-25 Chong Yidong <cyd@gnu.org> |
| 2 | 13 | ||
| 3 | * fileio.c (Ffile_selinux_context, Fset_file_selinux_context): | 14 | * fileio.c (Ffile_selinux_context, Fset_file_selinux_context): |
diff --git a/src/alloc.c b/src/alloc.c index 044e750413b..21c4db4ddca 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -1582,6 +1582,21 @@ make_number (EMACS_INT n) | |||
| 1582 | } | 1582 | } |
| 1583 | #endif | 1583 | #endif |
| 1584 | 1584 | ||
| 1585 | /* Convert the pointer-sized word P to EMACS_INT while preserving its | ||
| 1586 | type and ptr fields. */ | ||
| 1587 | static Lisp_Object | ||
| 1588 | widen_to_Lisp_Object (void *p) | ||
| 1589 | { | ||
| 1590 | intptr_t i = (intptr_t) p; | ||
| 1591 | #ifdef USE_LISP_UNION_TYPE | ||
| 1592 | Lisp_Object obj; | ||
| 1593 | obj.i = i; | ||
| 1594 | return obj; | ||
| 1595 | #else | ||
| 1596 | return i; | ||
| 1597 | #endif | ||
| 1598 | } | ||
| 1599 | |||
| 1585 | /*********************************************************************** | 1600 | /*********************************************************************** |
| 1586 | String Allocation | 1601 | String Allocation |
| 1587 | ***********************************************************************/ | 1602 | ***********************************************************************/ |
| @@ -4293,7 +4308,17 @@ mark_memory (void *start, void *end) | |||
| 4293 | 4308 | ||
| 4294 | for (pp = start; (void *) pp < end; pp++) | 4309 | for (pp = start; (void *) pp < end; pp++) |
| 4295 | for (i = 0; i < sizeof *pp; i += GC_POINTER_ALIGNMENT) | 4310 | for (i = 0; i < sizeof *pp; i += GC_POINTER_ALIGNMENT) |
| 4296 | mark_maybe_pointer (*(void **) ((char *) pp + i)); | 4311 | { |
| 4312 | void *w = *(void **) ((char *) pp + i); | ||
| 4313 | mark_maybe_pointer (w); | ||
| 4314 | |||
| 4315 | /* A host where a Lisp_Object is wider than a pointer might | ||
| 4316 | allocate a Lisp_Object in non-adjacent halves. If | ||
| 4317 | USE_LSB_TAG, the bottom half is not a valid pointer, so | ||
| 4318 | widen it to to a Lisp_Object and check it that way. */ | ||
| 4319 | if (sizeof w < sizeof (Lisp_Object)) | ||
| 4320 | mark_maybe_object (widen_to_Lisp_Object (w)); | ||
| 4321 | } | ||
| 4297 | } | 4322 | } |
| 4298 | 4323 | ||
| 4299 | /* setjmp will work with GCC unless NON_SAVING_SETJMP is defined in | 4324 | /* setjmp will work with GCC unless NON_SAVING_SETJMP is defined in |
diff --git a/src/lisp.h b/src/lisp.h index 375d376702b..36f58d05b42 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -197,22 +197,8 @@ extern int suppress_checking EXTERNALLY_VISIBLE; | |||
| 197 | # if defined DECL_ALIGN | 197 | # if defined DECL_ALIGN |
| 198 | /* On hosts where VALBITS is greater than the pointer width in bits, | 198 | /* On hosts where VALBITS is greater than the pointer width in bits, |
| 199 | USE_LSB_TAG is: | 199 | USE_LSB_TAG is: |
| 200 | 200 | a. unnecessary, because the top bits of an EMACS_INT are unused, and | |
| 201 | a. unnecessary, because the top bits of an EMACS_INT are unused, | 201 | b. slower, because it typically requires extra masking. |
| 202 | |||
| 203 | b. slower, because it typically requires extra masking, and | ||
| 204 | |||
| 205 | c. harmful, because it can create Lisp_Object values that are so scrambled | ||
| 206 | that mark_maybe_object cannot decipher them. mark_maybe_object assumes | ||
| 207 | that EMACS_INT values are contiguous, but a host where EMACS_INT is | ||
| 208 | wider than a pointer might allocate the top half of an EMACS_INT in | ||
| 209 | (say) a 32-bit word on the stack, putting the bottom half in a 32-bit | ||
| 210 | register that is saved elsewhere in a jmp_buf. When this happens, | ||
| 211 | since USE_LSB_TAG is not defined the bottom half alone is a valid | ||
| 212 | pointer that mark_maybe_pointer can follow; but if USE_LSB_TAG were | ||
| 213 | defined, the bottom half would not be a valid pointer and neither | ||
| 214 | mark_maybe_object nor mark_maybe_pointer would follow it. | ||
| 215 | |||
| 216 | So, define USE_LSB_TAG only on hosts where it might be useful. */ | 202 | So, define USE_LSB_TAG only on hosts where it might be useful. */ |
| 217 | # if UINTPTR_MAX >> VALBITS != 0 | 203 | # if UINTPTR_MAX >> VALBITS != 0 |
| 218 | # define USE_LSB_TAG | 204 | # define USE_LSB_TAG |