Bug#699722: src:libav: x264 decoding crashes

anton at khirnov.net anton at khirnov.net
Tue Feb 5 07:03:56 UTC 2013


Hi,
a Libav developer here.

This is really a bug/abuse of Libav API in xpra -- the file x264lib.c uses an
uninitialized AVFrame on stack. This has always been forbidden by Libav API, but
used to work until some changes a few months ago. Functions
avcodec_alloc_frame() and avcodec_free_frame() (in release 9 only, av_free() in
0.8 and earlier)  must be used to allocate and free an AVFrame.

Attached is a patch that fixes it.

-- 
Anton Khirnov
-------------- next part --------------
--- xpra/x264/x264lib.c	2013-01-01 08:26:41.000000000 +0100
+++ xpra/x264/x264lib1.c	2013-02-05 07:48:07.672379166 +0100
@@ -55,6 +55,7 @@
 	// Decoding
 	AVCodec *codec;
 	AVCodecContext *codec_ctx;
+	AVFrame *frame;
 	struct SwsContext *yuv2rgb;
 
 	// Encoding
@@ -251,6 +252,11 @@
 		fprintf(stderr, "could not open codec\n");
 		return 1;
 	}
+	ctx->frame = avcodec_alloc_frame();
+	if (!ctx->frame) {
+	    fprintf(stderr, "could not allocate an AVFrame for decoding\n");
+	    return 1;
+	}
 	return 0;
 }
 struct x264lib_ctx *init_decoder(int width, int height, int csc_fmt)
@@ -275,6 +281,7 @@
 		sws_freeContext(ctx->yuv2rgb);
 		ctx->yuv2rgb = NULL;
 	}
+	avcodec_free_frame(&ctx->frame);
 }
 void clean_decoder(struct x264lib_ctx *ctx)
 {
@@ -390,7 +397,7 @@
 	int got_picture;
 	int len;
 	int i;
-	AVFrame picture;
+	AVFrame *picture = ctx->frame;
 	AVPacket avpkt;
 
 	av_init_packet(&avpkt);
@@ -398,12 +405,12 @@
 	if (!ctx->codec_ctx || !ctx->codec)
 		return 1;
 
-	avcodec_get_frame_defaults(&picture);
+	avcodec_get_frame_defaults(picture);
 
 	avpkt.data = in;
 	avpkt.size = size;
 
-	len = avcodec_decode_video2(ctx->codec_ctx, &picture, &got_picture, &avpkt);
+	len = avcodec_decode_video2(ctx->codec_ctx, picture, &got_picture, &avpkt);
 	if (len < 0) {
 		fprintf(stderr, "Error while decoding frame\n");
 		memset(out, 0, sizeof(*out));
@@ -411,13 +418,13 @@
 	}
 
 	for (i = 0; i < 3; i++) {
-		(*out)[i] = picture.data[i];
-		*outsize += ctx->height * picture.linesize[i];
-		(*outstride)[i] = picture.linesize[i];
+		(*out)[i] = picture->data[i];
+		*outsize += ctx->height * picture->linesize[i];
+		(*outstride)[i] = picture->linesize[i];
 	}
 
     if (*outsize == 0) {
-        fprintf(stderr, "Decoded image, size %d %d %d, ptr %p %p %p\n", (*outstride)[0] * ctx->height, (*outstride)[1]*ctx->height, (*outstride)[2]*ctx->height, picture.data[0], picture.data[1], picture.data[2]);
+        fprintf(stderr, "Decoded image, size %d %d %d, ptr %p %p %p\n", (*outstride)[0] * ctx->height, (*outstride)[1]*ctx->height, (*outstride)[2]*ctx->height, picture->data[0], picture->data[1], picture->data[2]);
         return 3;
     }
 


More information about the pkg-multimedia-maintainers mailing list