Package: xscreensaver-gl Version: 6.09+dfsg1-2 Severity: minor Tags: patch glsnake's lighting depends on uninitialised stack memory. gl_init declares `float light_pos[][3]` and passes each row to glLightfv(GL_POSITION), which reads four floats. Light 0's w happens to be light_pos[1][0], which is 0.0. Light 1's w comes from past the array; valgrind reports "Conditional jump or move depends on uninitialised value(s)" from a stack allocation in gl_init.
The value is the low half of a pointer, so the picture changes between launches. A large w puts light 1 at the viewer, a small one puts it far off along (0, 20, -1) or the opposite way. With address randomisation on, 25 frames gave 9 different pictures; the light at the viewer was the most common, 17 of 25. With it off (setarch -R), 6 of 6 runs drew the same picture, but preloading a library that draws nothing changed 5.07 % of the pixels. The same code is in 6.17, the current upstream release. The attached patch gives both rows a w: light 0 keeps w = 0, and light 1 sits at the viewer, the picture most launches showed. Three pictures attached: light 1 as the sun (w = 0), at the viewer, and as a lamp at (0, 20, -1). In our own build the user can also pick among the three; that part is our choice and not part of this report. I found and measured this with the help of an AI assistant (Claude). Daniel These runs were in a Debian sid container; the kernel shown is the host's. -- System Information: Debian Release: forky/sid APT prefers unstable APT policy: (500, 'unstable') Architecture: amd64 (x86_64) Kernel: Linux 7.3.0-rc6-stereo3d8 (SMP w/12 CPU threads; PREEMPT) Kernel taint flags: TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE Locale: LANG=C, LC_CTYPE=C.UTF-8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /usr/bin/dash Init: unable to detect Versions of packages xscreensaver-gl depends on: ii libc6 2.43-7 ii libcap2-bin 1:2.78-1+b1 ii libegl1 1.7.0-3+b1 ii libgdk-pixbuf-2.0-0 2.44.8+dfsg-1 ii libgl1 1.7.0-3+b1 ii libglib2.0-0t64 2.90.1-2 ii libglu1-mesa [libglu1] 9.0.2-1.1+b4 ii libwww-perl 6.83-1 ii libx11-6 2:1.8.13-1 ii libxext6 2:1.3.4-1+b4 ii libxft2 2.3.6-1+b5 ii libxt6t64 1:1.2.1-1.3+b2 xscreensaver-gl recommends no packages. Versions of packages xscreensaver-gl suggests: pn xscreensaver <none>
Description: glsnake: give both light positions a w component glLightfv(GL_POSITION) reads four floats, but light_pos held three per light. Light 0's w was light_pos[1][0], which is 0.0. Light 1's w came from past the array, from stack memory that gl_init() never sets: valgrind's memcheck reports "Conditional jump or move depends on uninitialised value(s)" in the OpenGL driver, with the value "created by a stack allocation" in gl_init(). . That stray w is the low half of a pointer, so light 1 moved from run to run. With address randomisation on, 25 frames of earlier runs showed 9 different pictures. With it off (setarch -R), 6 of 6 stock runs drew the same picture, but preloading a library that draws nothing (an OpenGL layer with its output disabled) still changed 5.07% of the pixels, because it changes what was on the stack before gl_init(). . A large |w| puts light 1 at the viewer. That is the picture in 17 of the 25 frames and in all 6 runs with setarch -R. The authors' (0, 20, -1) only takes effect when w is small, and w = 0 would make light 1 a directional light that 1 of the 25 frames came near. Write light 0 out as it reads today, with w = 0, and put light 1 at the viewer, (0, 0, 0, 1): it draws that usual picture pixel for pixel, in every run. . XScreenSaver 6.17 has the same arrays, and memcheck reports the same read there (glsnake.c:1414). Author: Daniel Ramos (Capitain Jack) <[email protected]> Forwarded: no Last-Update: 2026-10-17 --- a/hacks/glx/glsnake.c +++ b/hacks/glx/glsnake.c @@ -1368,7 +1368,7 @@ static void gl_init( #endif ) { - float light_pos[][3] = {{0.0, 10.0, 20.0}, {0.0, 20.0, -1.0}}; + float light_pos[][4] = {{0.0, 10.0, 20.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}; float light_dir[][3] = {{0.0, -10.0,-20.0}, {0.0,-20.0, 1.0}}; glEnable(GL_DEPTH_TEST);

