Tk Source Code

View Ticket
Login
Ticket UUID: 187158195158f7934c1072e9a4c515c5a746532c
Title: Assertion failed in textIndex-19.12.2
Type: Bug Version: revised_text
Submitter: fvogel Created on: 2024-09-08 13:41:14
Subsystem: 18. [text] Assigned To: fvogel
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2024-09-14 07:32:26
Resolution: Fixed Closed By: fvogel
    Closed on: 2024-09-14 07:32:26
Description:

On macOS, Tk build with with symbols, --disable-aqua, running Tk tests under xvfb (like the CI runner) triggers:

---- textIndex-19.12.2 start
Assertion failed: (TkTextIndexCompare(indexPtr1, indexPtr2) <= 0), function TkTextIndexCountBytes, file tkTextIndex.c, line 3340.
/bin/sh: line 1: 13987 Abort trap: 6           ./tktest /Users/runner/work/tk/tk/tk/unix/../tests/all.tcl -geometry +0+0 -file textIndex.test -verbose t

User Comments: fvogel added on 2024-09-14 07:32:26:
Merged in the revised_text branch.

fvogel added on 2024-09-13 21:36:20:

While working on the fix for this ticket, I used a trick to reproduce the problem on Windows, on which platform I can debug more easily than on macOS with xvfb. The trick consisted in forcing the 'upToDate' variable in TkTextFindDisplayIndex() to be false, so that the required part of the code in that function got run instead of the other branch of the corresponding if. This was helpful and allowed me to find the [69bb32d896|fix].

In that process however I noticed that the code in TkTextFindDisplayIndex() does not always return the same value whether upToDate is true or false (whereas it should: only the computation method changes but the result should not). In particular, when upToDate is forced to be zero the textMark-6.6 test returns 1.9 (instead of 1.2 expected by the test suite). When upToDate is 1, this test returns 1.2. This should not happen: whatever the way the computation of the index is performed (i.e. whether of not the line metrics are already up-to-date or not), the result must be the same.

A bit of research showed that 1.9 is the correct value, and as a matter of fact this is precisely the result expected by the test suite for the legacy widget. The difference in behavior between the legacy text widget and the revised text widget that I had noticed in [bd98d3756c] while fixing ticket [34db75c0ac] actually was a bug of the revised text widget.

I have fixed this bug in [fd4362b48e]. Now both versions of the text widget behave the same in the case described in textMark-6.6.


fvogel added on 2024-09-10 20:17:25:

Fix in branch bug-1871581951.


fvogel added on 2024-09-08 15:19:13:

Analysis:

  • This is not always reproducible. Sometimes the assert triggers sometimes not. But it's easy to get (happens ~50% of the runs). This must be because for some runs the line metrics are already up-to-date, and for other runs it's not the case.
  • When the assert triggers during textIndex-19.12.2, string values of indexPtr1 and indexPtr2 in TkTextIndexCountBytes() are 3.40 and 3.39 respectively. This is indeed not supposed to happen (one should have TkTextIndexCompare(indexPtr1, indexPtr2) <= 0, i.e. ordered indices).
  • The call to TkTextIndexCountBytes() that leads to the assert triggering is in TkrTextIndexForwBytes() (tkTextIndex.c:3085). This line reads:
assert(!rc || (int) TkTextIndexCountBytes(&index, dstPtr) == byteCount);
  • At this point, the string values are index = 3.40 and dstPtr = 3.39. dstPtr is computed one line above by:
rc = TkBTreeMoveForward(dstPtr, byteCount);
  • At this point, byteCount is 0xffffffff (wrong).
  • The place where TkrTextIndexForwBytes() is called with such a byteCount value is in TkTextFindDisplayIndex(), at tkTextDisp.c:7757. Here the byteOffset value is 0xffffffff.
  • This byteOffset value is obtained two lines above from byteOffset = last->byteOffset; and last is computed to be info.entry + info.numDispLines;

I'm wondering if this loop is entirely correct. But if it is, then it's the byteOffset member of the last TkTextDispLineEntry that is incorrect.