This code in xdisp.c looks very suspicious to me:
------
static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
static int last_escape_glyph_merged_face_id = 0;
static int
merge_escape_glyph_face (struct it *it)
{
int face_id;
if (it->f == last_escape_glyph_frame
&& it->face_id == last_escape_glyph_face_id)
face_id = last_escape_glyph_merged_face_id;
else
{
/* Merge the `escape-glyph' face into the current face. */
face_id = merge_faces (it->f, Qescape_glyph, 0, it->face_id);
last_escape_glyph_frame = it->f;
last_escape_glyph_face_id = it->face_id;
last_escape_glyph_merged_face_id = face_id;
}
return face_id;
}
------
That caches a face id in last_escape_glyph_merged_face_id, which is cleared only in redisplay_internal(). But message() doesn't call redisplay_internal(), it calls try_window() directly (xdisp.c:10687) (and resize_window before that, which blows up).
This patch appears, so far, to run without a segfault (I neglected to record timings so can't give you a p-value, but back of the envelope it's >99% that it fixes the segfault), and it fixes what I think is a possible explanation for the segfault, so my current plan is to leave it running overnight and ask for inclusion (of this or an equivalent, cleaner patch, of course) if it doesn't blow up.
However, I have yet to look at the other bugs and doubt this is the whole story.