Subject: Effect of deletions on indirect buffers (Bug#8219)

From: Chong Yidong <[email-masked]>
Date: Fri, 11 Mar 2011 14:48:21 -0500

Indirect bufffers are allowed to have their own values of point,
BUF_BEGV, and BUF_ZV (indeed, that's one of their roles).  Their other
attributes inherit from the base buffer, e.g.

#define BUF_Z(buf) ((buf)->text->z)

where `text' points to the base buffer's text object.

Now consider what happens when a deletion is performed in buffer A,
which is the base buffer for an indirect buffer B.  It appears that the
responsible functions, such as del_range_2, only update the attributes
of buffer A, making no effort to update buffer B.

Hence, in the aftermath of a deletion, buffer B's values of PT (and
BUF_BEGV and BUF_ZV) can be larger than BUF_ZV.  This is the proximate
cause of the crash in Bug#8219: there, we have

 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
     && find_composition (prev_pt, -1, &start, &end, &prop, buffer)

and find_composition aborts because prev_pt is larger than the size of
the buffer.

I'm not sure what the best solution is.  The narrowest fix is to change
find_composition, and the functions it calls, so that it does not abort
when supplied with a position that's beyond BUF_Z.  This might be the
best approach for the emacs-23 branch.

However, I suspect that we have other places in the code that assumes
that if a point is smaller than BUF_ZV, it's necessarily smaller than
BUF_Z---which we now see if not that case.  So, a more comprehensive fix
is needed for the trunk.

Any thoughts?