Package: libvisual-0.4-plugins Version: 1:0.4.2+dfsg-6 Severity: normal Tags: patch upstream
JESS can crash when rendering an 8-bit surface through its non-MMX path. In render_blur(), bmax is initialized only inside the MMX branch, but is also used as the loop bound in the scalar branch. The resulting undefined behavior can make the loop run beyond the pixel buffer. I reproduced the SIGSEGV with a headless libvisual client rendering a 320x240 8-bit surface with synthetic stereo audio, on native amd64 and sh4 under QEMU. GDB stops in render_blur() at renderer.c:421, called by renderer(), act_jess_render() and visual_actor_run(). The preserved amd64 -6 binary also reproduces the crash; this is a pre-existing bug. The unchanged sh4 plugin completes the same test with a 32-bit surface. Moving the existing bmax assignment before the MMX/non-MMX branch fixes all 16 test frames on both native amd64 and sh4/QEMU. I submitted the runtime fix upstream: https://github.com/Libvisual/libvisual/pull/433 The Debian patch and regression test are committed on Salsa: https://salsa.debian.org/debian/libvisual-plugins/-/commit/de745fb The attached regression test explicitly disables MMX and exercises the 8-bit path. With libvisual-0.4-dev, a C compiler and pkgconf installed: cc -O2 -Wall -Wextra jess-8bit.c -o jess-8bit \ $(pkg-config --cflags --libs libvisual-0.4) ./jess-8bit The updated autopkgtest fails with exit 139 against the -6 package currently in unstable and passes with the local patched -7 candidate. The complete amd64 sbuild and Lintian source/binary checks also pass. Salsa CI pipeline #1203422 passed all 11 required jobs, including amd64/i386 builds, Lintian and the updated autopkgtest: https://salsa.debian.org/debian/libvisual-plugins/-/pipelines/1203422 The candidate remains UNRELEASED and has not been uploaded. Best regards, Federico
030_fix_jess_8bit_blur.patch
Description: Binary data
/* Exercise JESS's scalar 8-bit rendering path with synthetic audio. */
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <libvisual/libvisual.h>
static void require(int ok, const char *operation)
{
if (!ok) {
fprintf(stderr, "JESS 8-bit test failed: %s\n", operation);
exit(1);
}
}
int main(int argc, char **argv)
{
require(visual_init(&argc, &argv) == 0, "initialize libvisual");
visual_cpu_set_mmx(0);
require(visual_cpu_get_mmx() == 0, "disable MMX");
VisActor *actor = visual_actor_new("jess");
require(actor != NULL, "load JESS");
require(visual_actor_realize(actor) == 0, "initialize JESS");
VisVideo *video = visual_video_new_with_buffer(320, 240,
VISUAL_VIDEO_DEPTH_8BIT);
VisAudio *audio = visual_audio_new();
require(video != NULL && audio != NULL, "allocate video and audio");
require(visual_actor_set_video(actor, video) == 0, "set video");
require(visual_actor_video_negotiate(actor, 0, 0, 0) == 0,
"negotiate video");
int16_t pcm[1024];
VisBuffer *buffer = visual_buffer_new_with_buffer(pcm, sizeof(pcm), NULL);
require(buffer != NULL, "allocate audio buffer");
unsigned int nonzero = 0;
for (int frame = 0; frame < 16; frame++) {
for (int i = 0; i < 1024; i++)
pcm[i] = (int16_t)(16000.0 * sin((i + frame * 1024) * 0.05));
require(visual_audio_samplepool_input(audio->samplepool, buffer,
VISUAL_AUDIO_SAMPLE_RATE_44100,
VISUAL_AUDIO_SAMPLE_FORMAT_S16,
VISUAL_AUDIO_SAMPLE_CHANNEL_STEREO) == 0,
"feed audio");
require(visual_actor_run(actor, audio) == 0, "render frame");
const unsigned char *pixels = visual_video_get_pixels(video);
require(pixels != NULL, "get rendered pixels");
for (int i = 0; i < visual_video_get_size(video); i++)
nonzero += pixels[i] != 0;
}
require(nonzero > 0, "produce rendered output");
printf("JESS scalar 8-bit: 16 frames PASS (%u nonzero pixels)\n", nonzero);
visual_object_unref(VISUAL_OBJECT(buffer));
visual_object_unref(VISUAL_OBJECT(actor));
visual_object_unref(VISUAL_OBJECT(video));
visual_object_unref(VISUAL_OBJECT(audio));
visual_quit();
return 0;
}

