Subject: Re: Tracking a crasher...
From: Jesper Skov (jskov@redhat.com)
Date: Sun Jan 21 2001 - 13:25:14 CST
>>>>> "Jesper" == Jesper Skov <jskov@redhat.com> writes:
Jesper> Martin mentioned a crasher which was found by Thomas
Jesper> Fletcher's colleague. It's quite easy to reproduce:
Jesper> 1<line-break>2<cursor up><return>[*boom*]
Found it.
This is what the fmt engine contains before pressing return:
(gdb) p ::__dump()
FL_DocLayout::__dump(0x0x84985b0) contains 1 pages.
Page: 0x0x849ea30
FL_DocLayout::__dump(0x0x84985b0) sections:
Section: 0x0x8498bf8 [type 1]
Block: 0x0x8498d28 [sdh 0x0x84983d8]
Run: 0x84b45b0 T=Text Off=0 Len=0 D=n Line=0x8499250 [x 0 y 0 w 0 h 18]
Run: 0x84b4060 T=Text Off=0 Len=1 D=n Line=0x8499250 [x 0 y 0 w 8 h 18]
[1]
Run: 0x84b44f0 T=LineBreak Off=1 Len=1 D=n Line=0x8499250 [x 8 y 0 w 0 h 0]
Run: 0x8499058 T=Text Off=2 Len=1 D=n Line=0x84b4550 [x 0 y 0 w 8 h 18]
[
]
Block: 0x0x84b48e8 [sdh 0x0x84b4868]
fl_BlockLayout::doclistener_insertBlock is tasked with the job of
finding the place where to split an existing block or insert a new
one.
In this case, we want the split between Runs 0x84b4060 and
0x84b44f0. Problem is the below code:
/*
The idea here is to divide the runs of the existing block
into two equivalence classes. This may involve
splitting an existing run.
All runs and lines remaining in the existing block are
fine, although the last run should be redrawn.
All runs in the new block need their offsets fixed, and
that entire block needs to be formatted from scratch.
TODO is the above commentary still correct ??
*/
// figure out where the breakpoint is
PT_BlockOffset blockOffset = (pcrx->getPosition() - getPosition());
fp_Run* pFirstNewRun = NULL;
fp_Run* pLastRun = NULL;
fp_Run* pRun;
for (pRun=m_pFirstRun; (pRun && !pFirstNewRun); pLastRun=pRun, pRun=pRun->getNext())
{
switch (pRun->containsOffset(blockOffset))
{
case FP_RUN_INSIDE:
if (blockOffset > pRun->getBlockOffset())
{
UT_ASSERT(pRun->getType() == FPRUN_TEXT);
// split here
fp_TextRun* pTextRun = (fp_TextRun*) pRun;
pTextRun->split(blockOffset);
pFirstNewRun = pRun->getNext();
}
else
{
pFirstNewRun = pRun;
}
break;
case FP_RUN_NOT:
break;
default:
UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
break;
}
}
containsOffset() on the LineBreak always returns fail.
The cure, which I've discussed with Mike before, is rewriting those
loops that expect the callee to tell the location, even though it
doesn't have the necessary info, to something where the caller handles
overflows in a sensible way.
I'll try to cook up something, and we can discuss it.
Jesper
This archive was generated by hypermail 2b25 : Sun Jan 21 2001 - 13:25:19 CST