Crash program with cairo_recording_surface_create and with big rectangle size

Uli Schlachter psychon at znc.in
Sat Mar 16 18:08:27 UTC 2024


Hi,

Am 15.03.24 um 13:28 schrieb Kęstutis:
> What is the maximum width and height of a rectangle that I can use with 
> the recording surface?

 From the top of my head: I don't know about any limits.

> When I attempted to use a rectangle with dimensions of 39000x57400, the 
> program crashed with a General Protection Fault (GPF) due to an endless 
> recursion occurring in the function |bbtree_add| within the module 
> |cairo-recording-surface.c|.
> 
> I have attached an example of the program.
> 
> Could someone please provide assistance with this situation?

Sure. My first thought is: Here is the link to the issue tracker [1].

[1]: https://gitlab.freedesktop.org/freedesktop/freedesktop/-/issues/new

> Thank you for any insights and best regards.

I have no clue about this code, so I did some printf-debugging. The 
patch is attached. With this patch, your program produces repeated 
output like the following (the pointers of course differ, but the 
coordinates stay the same in the many calls):

bbtree_left_or_right(bbt{left=(nil), right=(nil)}, box=(8352000, 
14707200) to (8606720, 14745088))
left=0
right=0
left_or_right returning 1

bbtree_left_or_right(bbt{left=0x564b424aec00, right=(nil)}, box=(0, 0) 
to (9984000, 14694400))
bbt->left_extents=(8352000, 14707200) to (8606720, 14745088)
Union=(0, 0) to (9984000, 14745088)
left=-2048792556
right=0
left_or_right returning 1

The value for "left" in the second call obviously looks like an integer 
overflow. Also, bbt->left_extents look invalid there. If I understand 
this code correctly, cairo_box_t is a rectangle where p1 is the upper 
left corner and p2 is the lower right corner.

The coordinates in a cairo_box_t are saved as a cairo_fixed_t, which is 
a fixed point number. 24 bits are used for the integer part and 8 bits 
for the fractional part. So, just from this, I guess that the possible 
value range is between -2^23 and 2^23 - 1. Just from the numbers, your 
program stays within these limits. However, I don't know what happens 
with the text with this large font size or the transformation matrix. 
Perhaps some coordinate ends up being larger than this and the resulting 
integer overflow breaks everything?

Going back to the output above...

bbt->left_extents=(8352000, 14707200) to (8606720, 14745088)
Union=(0, 0) to (9984000, 14745088)

...decoding (= divide by 2^8) the fixed point numbers results in:

bbt->left_extents=(32625.00, 57450.00) to (33620.00, 57598.00)
Union=(0, 0) to (39000.00, 57598.00)

Hm....
The code in bbtree_left_or_right() computes left as (width-of-union * 
height-of-union) - (width-of-extends) * (height-of-extends). So... if I 
understand this correctly, this computes the difference of the areas of 
the two boxes and because these boxes are so huge, there is an overflow?

(The code also uses _cairo_fixed_integer_part() to only look at full 
pixels within? Or perhaps this is supposed to protect against overflows 
by making the numbers slightly smaller? I don't know.)

Changing the type of "left" and "right" to "int64_t" and adding a cast 
to int64_t to the multiplication changes the complete output of the test 
case to:

bbtree_left_or_right(bbt{left=(nil), right=(nil)}, box=(8352000, 
14707200) to (8606720, 14745088))
left=0
right=0
left_or_right returning 1

bbtree_left_or_right(bbt{left=0x55e6572fc570, right=(nil)}, box=(0, 0) 
to (9984000, 14694400))
bbt->left_extents=(8352000, 14707200) to (8606720, 14745088)
Union=(0, 0) to (9984000, 14745088)
left=2246174740
right=0
left_or_right returning 0

bbtree_left_or_right(bbt{left=(nil), right=(nil)}, box=(102400, 57344) 
to (430336, 100352))
left=0
right=0
left_or_right returning 1

This change is also attached as a patch. Perhaps that can be included in 
your bug report.

Cheers,
Uli
-- 
Do you remember what we used to say back then?
One impossible thing at a time.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: printf.patch
Type: text/x-diff
Size: 2177 bytes
Desc: not available
URL: <https://lists.cairographics.org/archives/cairo/attachments/20240316/613aab5d/attachment.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: possible_fix.patch
Type: text/x-diff
Size: 1075 bytes
Desc: not available
URL: <https://lists.cairographics.org/archives/cairo/attachments/20240316/613aab5d/attachment-0001.patch>


More information about the cairo mailing list