diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2012-02-25 11:39:42 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2012-02-25 11:39:42 -0800 |
commit | cdecb2652c77d4c8e3572811b5da5dda464ec8db (patch) | |
tree | cc4ff09051576ece916d77e7c9795cd6f9093e51 | |
parent | 7b59b27a17fa2275d27837efac27310f99449b6d (diff) | |
download | emacs-cdecb2652c77d4c8e3572811b5da5dda464ec8db.tar.gz |
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.
-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 e3f8aba09d0..1f8c00b31f7 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2012-02-25 Paul Eggert <eggert@cs.ucla.edu> + + 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. + 2012-02-25 Chong Yidong <cyd@gnu.org> * 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) } #endif +/* Convert the pointer-sized word P to EMACS_INT while preserving its + type and ptr fields. */ +static Lisp_Object +widen_to_Lisp_Object (void *p) +{ + intptr_t i = (intptr_t) p; +#ifdef USE_LISP_UNION_TYPE + Lisp_Object obj; + obj.i = i; + return obj; +#else + return i; +#endif +} + /*********************************************************************** String Allocation ***********************************************************************/ @@ -4293,7 +4308,17 @@ mark_memory (void *start, void *end) for (pp = start; (void *) pp < end; pp++) for (i = 0; i < sizeof *pp; i += GC_POINTER_ALIGNMENT) - mark_maybe_pointer (*(void **) ((char *) pp + i)); + { + void *w = *(void **) ((char *) pp + i); + mark_maybe_pointer (w); + + /* A host where a Lisp_Object is wider than a pointer might + allocate a Lisp_Object in non-adjacent halves. If + USE_LSB_TAG, the bottom half is not a valid pointer, so + widen it to to a Lisp_Object and check it that way. */ + if (sizeof w < sizeof (Lisp_Object)) + mark_maybe_object (widen_to_Lisp_Object (w)); + } } /* 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; # if defined DECL_ALIGN /* On hosts where VALBITS is greater than the pointer width in bits, USE_LSB_TAG is: - - a. unnecessary, because the top bits of an EMACS_INT are unused, - - b. slower, because it typically requires extra masking, and - - c. harmful, because it can create Lisp_Object values that are so scrambled - that mark_maybe_object cannot decipher them. mark_maybe_object assumes - that EMACS_INT values are contiguous, but a host where EMACS_INT is - wider than a pointer might allocate the top half of an EMACS_INT in - (say) a 32-bit word on the stack, putting the bottom half in a 32-bit - register that is saved elsewhere in a jmp_buf. When this happens, - since USE_LSB_TAG is not defined the bottom half alone is a valid - pointer that mark_maybe_pointer can follow; but if USE_LSB_TAG were - defined, the bottom half would not be a valid pointer and neither - mark_maybe_object nor mark_maybe_pointer would follow it. - + a. unnecessary, because the top bits of an EMACS_INT are unused, and + b. slower, because it typically requires extra masking. So, define USE_LSB_TAG only on hosts where it might be useful. */ # if UINTPTR_MAX >> VALBITS != 0 # define USE_LSB_TAG |