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.
This commit is contained in:
Paul Eggert 2012-02-25 11:39:42 -08:00
parent 2345325552
commit 27f3c6378b
3 changed files with 39 additions and 17 deletions

View file

@ -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):

View file

@ -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

View file

@ -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