Subject: bug#52461: spontaneous crash with portable dumper

From: Pip Cet <[email-masked]>
Date: Mon, 13 Dec 2021 14:43:55 +0000

On Mon, Dec 13, 2021 at 1:53 PM Eli Zaretskii <[email-masked]> wrote:
> > Date: Mon, 13 Dec 2021 10:38:28 +0900
> > From: YAMAMOTO Mitsuharu <[email-masked]>
> >
> > (lldb) p cs_i
> > (int) $2 = 183
> > (lldb) p charset_table_used
> > (int) $3 = 183
> >
> > Because cs_i >= charset_table_used, charset_table[cs_i] (i.e., *cs)
> > contains uninitialized contents.
>
> So we somehow have a charset that is not in charset_table, is that
> what you are saying?  Because otherwise how could its ID be beyond the
> table, when define-charset-internal enlarges the table as needed?

I think there's no great mystery here, and the initial analysis is correct:

define-charset-internal enlarges the table, but doesn't zero out the
added entries (>= charset_table_used, < charset_table_size). pdumper
assumes all entries (< charset_table_size), including the unused ones,
contain either valid pointers or NULL. When they're not, but happen to
have an invalid pointer in the wrong place, we get a crash.

Often, realloc will return zeroed memory so this bug may have stayed
invisible for some time.

What we can try is debugging the crashing temacs binary, setting a
breakpoint to the point where define-charset-internal calls xpalloc
(in a very strange manner), at about line 1126 in charset.c, and zero
the memory after the call by executing
  memset (new_table, 0, new_size * sizeof (new_table[0]))
in the debugger (I don't use lldb so I'm not sure precisely how to do
that), then continuing to the memcpy.

If that fixes things, we should make the obvious change, I think.

Pip