summaryrefslogtreecommitdiff
path: root/libavcodec/qtrle.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/qtrle.c')
-rw-r--r--libavcodec/qtrle.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c
index 3f173a596b..d02dffae6a 100644
--- a/libavcodec/qtrle.c
+++ b/libavcodec/qtrle.c
@@ -2,20 +2,20 @@
* Quicktime Animation (RLE) Video Decoder
* Copyright (C) 2004 the ffmpeg project
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -62,6 +62,15 @@ static void qtrle_decode_1bpp(QtrleContext *s, int row_ptr, int lines_to_change)
unsigned char *rgb = s->frame.data[0];
int pixel_limit = s->frame.linesize[0] * s->avctx->height;
int skip;
+ /* skip & 0x80 appears to mean 'start a new line', which can be interpreted
+ * as 'go to next line' during the decoding of a frame but is 'go to first
+ * line' at the beginning. Since we always interpret it as 'go to next line'
+ * in the decoding loop (which makes code simpler/faster), the first line
+ * would not be counted, so we count one more.
+ * See: https://ffmpeg.org/trac/ffmpeg/ticket/226
+ * In the following decoding loop, row_ptr will be the position of the
+ * _next_ row. */
+ lines_to_change++;
while (lines_to_change) {
skip = bytestream2_get_byte(&s->g);
@@ -70,12 +79,15 @@ static void qtrle_decode_1bpp(QtrleContext *s, int row_ptr, int lines_to_change)
break;
if(skip & 0x80) {
lines_to_change--;
- row_ptr += row_inc;
pixel_ptr = row_ptr + 2 * (skip & 0x7f);
+ row_ptr += row_inc;
} else
pixel_ptr += 2 * skip;
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
+ if(rle_code == -1)
+ continue;
+
if (rle_code < 0) {
/* decode the run length code */
rle_code = -rle_code;
@@ -114,6 +126,7 @@ static inline void qtrle_decode_2n4bpp(QtrleContext *s, int row_ptr,
while (lines_to_change--) {
pixel_ptr = row_ptr + (num_pixels * (bytestream2_get_byte(&s->g) - 1));
+ CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
if (rle_code == 0) {
@@ -168,6 +181,7 @@ static void qtrle_decode_8bpp(QtrleContext *s, int row_ptr, int lines_to_change)
while (lines_to_change--) {
pixel_ptr = row_ptr + (4 * (bytestream2_get_byte(&s->g) - 1));
+ CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
if (rle_code == 0) {
@@ -217,6 +231,7 @@ static void qtrle_decode_16bpp(QtrleContext *s, int row_ptr, int lines_to_change
while (lines_to_change--) {
pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 2;
+ CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
if (rle_code == 0) {
@@ -260,6 +275,7 @@ static void qtrle_decode_24bpp(QtrleContext *s, int row_ptr, int lines_to_change
while (lines_to_change--) {
pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 3;
+ CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
if (rle_code == 0) {
@@ -306,6 +322,7 @@ static void qtrle_decode_32bpp(QtrleContext *s, int row_ptr, int lines_to_change
while (lines_to_change--) {
pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 4;
+ CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */
while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
if (rle_code == 0) {
@@ -376,6 +393,7 @@ static av_cold int qtrle_decode_init(AVCodecContext *avctx)
return AVERROR_INVALIDDATA;
}
+ avcodec_get_frame_defaults(&s->frame);
s->frame.data[0] = NULL;
return 0;
@@ -391,7 +409,7 @@ static int qtrle_decode_frame(AVCodecContext *avctx,
int has_palette = 0;
bytestream2_init(&s->g, avpkt->data, avpkt->size);
- s->frame.reference = 1;
+ s->frame.reference = 3;
s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
if (avctx->reget_buffer(avctx, &s->frame)) {
@@ -417,6 +435,8 @@ static int qtrle_decode_frame(AVCodecContext *avctx,
bytestream2_skip(&s->g, 2);
height = bytestream2_get_be16(&s->g);
bytestream2_skip(&s->g, 2);
+ if (height > s->avctx->height - start_line)
+ goto done;
} else {
start_line = 0;
height = s->avctx->height;