Tk Source Code

View Ticket
Login
Ticket UUID: 2712f43f6ecd4c10fae07857e2cc985179fffea3
Title: X11: fix crash for rotated text w/o Xft
Type: Patch Version: core-8-6-branch
Submitter: chrstphrchvz Created on: 2020-04-23 05:20:20
Subsystem: 05. Canvas Items Assigned To: fvogel
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2020-05-01 11:58:22
Resolution: Fixed Closed By: fvogel
    Closed on: 2020-05-01 11:58:22
Description:

Found while testing [7655f65ae7].

On X11 without Xft support enabled, if a canvas text item has a non-zero -angle and a -fill color distinct from the -selectforeground color of the canvas, then attempting to select a range of the item's text which includes the first character of text (on the first line) causes Tk to crash, due to a failed X request similar to the following:

X Error of failed request:  BadValue (integer parameter out of range for operation)
  Major opcode of failed request:  53 (X_CreatePixmap)
  Value in failed request:  0x0
  Serial number of failed request:  40984
  Current serial number in output stream:  40985

Example script to trigger the error automatically:

package require Tk

tk scaling 1.0

canvas .c -background bisque -selectforeground green2 grid .c set id [.c create text 50 150 -anchor w -text "Angled text" -angle 30 -font {Helvetica 32} -fill darkblue]

for {set sel_start 8} {$sel_start >= 0} {incr sel_start -1} { .c select clear .c select from $id $sel_start .c select to $id 8 update after 300 }

How the crash happens: DisplayCanvText() (tkCanvText.c) draws the first unselected portion of text (which in this case is empty*) with TkDrawAngledTextLayout() (tkFont.c), which in turn uses TkDrawAngledChars() (tkUnixFont.c) since angle != 0.0 for rotated text, which then uses GetImageOfText(), which uses Tk_MeasureChars() to obtain width, which is 0 for an empty unselected text portion. This width is then used with Tk_GetPixmap() (a wrapper for XCreatePixmap()) and various Xlib functions which require positive width and height, and will generate a BadValue error otherwise. (Using XSync(display, 0) confirms Tk_GetPixmap() is the first erroneously called command; otherwise the error may not be apparent until several more X11 commands are queued.)

I will attach a patch that fixes the issue by having GetImageOfText() check for (width > 0) && (height > 0) before using any Xlib functions requiring this be the case, and have it return NULL otherwise, which TkDrawAngledChars() already handles by returning early. I also propose adding similar checks to InitDestImage(), even though once the checks in GetImageOfText() are added, InitDestImage() will never be called with non-positive width or height.

*An optimization is to skip drawing empty unselected portions of text, which I will provide in a separate patch; while doing so would work around the issue, it would be better if calling TkDrawAngledTextLayout() with firstChar ≥ lastChar ≥ 0 didn't crash.

User Comments: fvogel added on 2020-05-01 11:58:22:
Merged in core-8-6-branch and trunk.

fvogel added on 2020-04-26 21:08:04:
Correct, I have changed the comment.

chrstphrchvz added on 2020-04-26 20:37:33:

I notice the new test added in [2d463458cb], however I believe the comment should refer to this issue as existing under X11 generally, and not just Linux specifically. I haven't tested this specific issue on BSD, XQuartz, etc., but I don't see why they wouldn't be affected.


fvogel added on 2020-04-26 20:32:46:
I have added a non-regression test canvText-20.2, failing before the fix and passing with it. I could confirm the failure and the fix on Debian 9, without Xft (--disable-xft).

fvogel added on 2020-04-23 21:08:28:

Thank you very much, this is entirely correct. I have committed your both patches to branch bug-2712f43f6e.


chrstphrchvz added on 2020-04-23 16:32:59:

I have now attached the optimization patch, which skips drawing empty unselected portions of canvas text, and also explicitly specifies textPtr->numChars instead of -1 as the lastChar argument for TkDrawAngledTextLayout().


Attachments: