Assertion failure accessing pixel-bytes of default-constructed GdkPixbuf, causing GTK 3 test failure
Steps to reproduce
Construct a trivial GdkPixbuf
and access its pixel-bytes
property. For example, at an interactive Python prompt:
>>> from gi.repository import GdkPixbuf
>>> GdkPixbuf.Pixbuf().props.pixel_bytes
Expected result
Either NULL
, a valid zero-length GBytes
or a 1x1 pixel GBytes
(of some arbitrary colour), with no criticals or warnings - I'm not sure which would be the most correct
Actual result
This GLib critical warning:
__main__:1: Warning: g_bytes_new: assertion 'data != NULL || size == 0' failed
Impact
The same issue causes the GTK+ 3.24.0 test suite to fail when run against gdk-pixbuf 2.38.0 (2.36.12 is OK):
(/srv/tmp/smcv/build-area/gtk+3.0-3.24.0/debian/build/deb/testsuite/gtk/.libs/defaultvalue:8467): GLib-CRITICAL **: 00:19:27.089: g_bytes_new: assertion 'data != NULL || size == 0' failed
Further analysis
#4 0x00007ffff6ce4450 in gdk_pixbuf_get_property (object=0x555555784b00, prop_id=9, value=0x7fffffffdad0, pspec=0x55555582ad40) at ../gdk-pixbuf/gdk-pixbuf.c:1345
Line 1345 is:
case PROP_PIXEL_BYTES:
g_value_set_boxed (value, gdk_pixbuf_read_pixel_bytes (pixbuf));
In the mode where the GdkPixbuf is backed by mutable pixels and not an
immutable GBytes structure, this returns:
return g_bytes_new (pixbuf->s.pixels.pixels,
gdk_pixbuf_get_byte_length (pixbuf));
where gdk_pixbuf_get_byte_length() returns:
return ((pixbuf->height - 1) * pixbuf->rowstride +
pixbuf->width * ((pixbuf->n_channels * pixbuf->bits_per_sample + 7) / 8));
(gdb) p *(GdkPixbuf *)object
$1 = {parent_instance = {g_type_instance = {Python Exception <class 'gdb.error'> No type named TypeNode.:
g_class = }, ref_count = 2, qdata = 0x0},
colorspace = GDK_COLORSPACE_RGB, n_channels = 3, bits_per_sample = 8, width = 1, height = 1, rowstride = 1,
storage = STORAGE_PIXELS, s = {pixels = {pixels = 0x0, destroy_fn = 0x0, destroy_fn_data = 0x0}, bytes = {
bytes = 0x0}}, has_alpha = 0}
So the calculation is that this 1x1 GdkPixbuf should have 3 bytes of
data, namely the R,G,B values of its single pixel.
Before 2.38 the pixel-bytes
property would have been NULL whenever not backed by a GBytes, even if there was a non-NULL pixel data blob (which also seems like a bug).