Source: gtk4
Version: 4.20.2+ds-1
Severity: serious
Tags: ftbfs upstream
Justification: fails unit tests at the end of the build process
X-Debbugs-Cc: [email protected]
The gtk4 package build currently fails on architectures with strict memory
alignment rules, namely sparc64.
The errors manifest as bus errors due to unaligned memory access in unit tests
for mipmap conversion routines. [1]
These unit test use the helper function texture_builder_init[2], which
unconditionally calls gdk_memory_layout_init[3] and gdk_memory_layout_fudge[4]
with a required memory alignment of 1 byte.
gdk_memory_layout_fudge[4] will then generate a randomized memory layout for
storing pixel data.
This function would actually honor a requested memory alignment, but not if the
alignment is always 1.
With a requested alignment of 1, it may generate data offsets that cause errors
when accessing 16- or 32-bit pixel formats, which must be aligned at 2 or 4
byte boundaries on sparc64.
I can see several possible fixes for this issue:
1. Always enforce the minimum required alignment based on the underlying data
types. This is the most drastic change and will require modifying
gdk_memory_layout_init.[2]
2. Enforce the minimum required alignment only on CPU architectures that
require it. This would fix the issue, but may also cause problems when a
specific memory layout is expected by an application.
3. Fix the unit test by always requesting a memory layout with adequate
alignment in texture_builder_init.[2]
Option 3. seems to be the most prudent, since it wouldn't cause problems on
other architectures where the memory alignment doesn't matter.
On the other hand, it would hide the fact that inadequate memory alignments in
user programs may lead to crashes when the target CPU doesn't support it.
I've included an untested patch for option 3.
[1] testsuite/gdk/mipmap.c
https://salsa.debian.org/gnome-team/gtk4/-/blob/debian/latest/testsuite/gdk/mipmap.c?ref_type=heads#L234
[2] testsuite/gdk/gdktestutils.c:texture_builder_init
https://salsa.debian.org/gnome-team/gtk4/-/blob/debian/latest/testsuite/gdk/gdktestutils.c?ref_type=heads#L656
[3] gdk/gdkmemorylayout.c:gdk_memory_layout_init
https://salsa.debian.org/gnome-team/gtk4/-/blob/debian/latest/gdk/gdkmemorylayout.c#L39
[4] testsuite/gdk/gdktestutils.c:gdk_memory_layout_fudge
https://salsa.debian.org/gnome-team/gtk4/-/blob/debian/latest/testsuite/gdk/gdktestutils.c?ref_type=heads#L635
-- System Information:
Debian Release: forky/sid
APT prefers unreleased
APT policy: (500, 'unreleased'), (500, 'unstable')
Architecture: sparc64
Kernel: Linux 6.16.12+deb14+1-sparc64 (UP)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8),
LANGUAGE=en_US:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
--- gtk4/testsuite/gdk/gdktestutils.c 2025-10-16 22:15:43.620309363 +0200
+++ gdktestutils.c 2025-10-25 02:04:24.709349454 +0200
@@ -177,6 +177,89 @@
}
}
+gsize
+gdk_memory_format_get_alignment (GdkMemoryFormat format)
+{
+ switch (format)
+ {
+ case GDK_MEMORY_R8G8B8:
+ case GDK_MEMORY_B8G8R8:
+ case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
+ case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
+ case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
+ case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
+ case GDK_MEMORY_B8G8R8A8:
+ case GDK_MEMORY_A8R8G8B8:
+ case GDK_MEMORY_R8G8B8A8:
+ case GDK_MEMORY_A8B8G8R8:
+ case GDK_MEMORY_B8G8R8X8:
+ case GDK_MEMORY_X8R8G8B8:
+ case GDK_MEMORY_R8G8B8X8:
+ case GDK_MEMORY_X8B8G8R8:
+ case GDK_MEMORY_G8:
+ case GDK_MEMORY_G8A8:
+ case GDK_MEMORY_G8A8_PREMULTIPLIED:
+ case GDK_MEMORY_A8:
+ case GDK_MEMORY_G8_B8R8_420:
+ case GDK_MEMORY_G8_R8B8_420:
+ case GDK_MEMORY_G8_B8R8_422:
+ case GDK_MEMORY_G8_R8B8_422:
+ case GDK_MEMORY_G8_B8R8_444:
+ case GDK_MEMORY_G8_R8B8_444:
+ case GDK_MEMORY_G8_B8_R8_410:
+ case GDK_MEMORY_G8_R8_B8_410:
+ case GDK_MEMORY_G8_B8_R8_411:
+ case GDK_MEMORY_G8_R8_B8_411:
+ case GDK_MEMORY_G8_B8_R8_420:
+ case GDK_MEMORY_G8_R8_B8_420:
+ case GDK_MEMORY_G8_B8_R8_422:
+ case GDK_MEMORY_G8_R8_B8_422:
+ case GDK_MEMORY_G8_B8_R8_444:
+ case GDK_MEMORY_G8_R8_B8_444:
+ case GDK_MEMORY_G8B8G8R8_422:
+ case GDK_MEMORY_G8R8G8B8_422:
+ case GDK_MEMORY_R8G8B8G8_422:
+ case GDK_MEMORY_B8G8R8G8_422:
+ return 1;
+
+ case GDK_MEMORY_R16G16B16:
+ case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
+ case GDK_MEMORY_R16G16B16A16:
+ case GDK_MEMORY_G16:
+ case GDK_MEMORY_G16A16:
+ case GDK_MEMORY_G16A16_PREMULTIPLIED:
+ case GDK_MEMORY_A16:
+ case GDK_MEMORY_G10X6_B10X6R10X6_420:
+ case GDK_MEMORY_G12X4_B12X4R12X4_420:
+ case GDK_MEMORY_G16_B16R16_420:
+ case GDK_MEMORY_X6G10_X6B10_X6R10_420:
+ case GDK_MEMORY_X6G10_X6B10_X6R10_422:
+ case GDK_MEMORY_X6G10_X6B10_X6R10_444:
+ case GDK_MEMORY_X4G12_X4B12_X4R12_420:
+ case GDK_MEMORY_X4G12_X4B12_X4R12_422:
+ case GDK_MEMORY_X4G12_X4B12_X4R12_444:
+ case GDK_MEMORY_G16_B16_R16_420:
+ case GDK_MEMORY_G16_B16_R16_422:
+ case GDK_MEMORY_G16_B16_R16_444:
+ case GDK_MEMORY_R16G16B16_FLOAT:
+ case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
+ case GDK_MEMORY_R16G16B16A16_FLOAT:
+ case GDK_MEMORY_A16_FLOAT:
+ return 2;
+
+ case GDK_MEMORY_R32G32B32_FLOAT:
+ case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
+ case GDK_MEMORY_R32G32B32A32_FLOAT:
+ case GDK_MEMORY_A32_FLOAT:
+ return 4;
+
+ case GDK_MEMORY_N_FORMATS:
+ default:
+ g_assert_not_reached ();
+ return 1;
+ }
+}
+
void
gdk_memory_pixel_print (const guchar *data,
const GdkMemoryLayout *layout,
@@ -658,8 +741,11 @@
int width,
int height)
{
- gdk_memory_layout_init (&builder->layout, format, width, height, 1);
- gdk_memory_layout_fudge (&builder->layout, 1);
+ gsize align;
+
+ align = gdk_memory_format_get_alignment (format);
+ gdk_memory_layout_init (&builder->layout, format, width, height, align);
+ gdk_memory_layout_fudge (&builder->layout, align);
builder->pixels = g_malloc0 (builder->layout.size);
}