sgidec: fix buffer size check in expand_rle_row()
Right now it will spuriously fail if the linesize is exactly equal to the data width. CC:libav-stable@libav.org
This commit is contained in:
		
				
					committed by
					
						
						Sean McGovern
					
				
			
			
				
	
			
			
			
						parent
						
							ff409c7d80
						
					
				
				
					commit
					ea1806ce65
				
			@@ -26,6 +26,7 @@
 | 
				
			|||||||
#include "sgi.h"
 | 
					#include "sgi.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct SgiState {
 | 
					typedef struct SgiState {
 | 
				
			||||||
 | 
					    AVCodecContext *avctx;
 | 
				
			||||||
    AVFrame picture;
 | 
					    AVFrame picture;
 | 
				
			||||||
    unsigned int width;
 | 
					    unsigned int width;
 | 
				
			||||||
    unsigned int height;
 | 
					    unsigned int height;
 | 
				
			||||||
@@ -39,12 +40,12 @@ typedef struct SgiState {
 | 
				
			|||||||
 * Expand an RLE row into a channel.
 | 
					 * Expand an RLE row into a channel.
 | 
				
			||||||
 * @param s the current image state
 | 
					 * @param s the current image state
 | 
				
			||||||
 * @param out_buf Points to one line after the output buffer.
 | 
					 * @param out_buf Points to one line after the output buffer.
 | 
				
			||||||
 * @param out_end end of line in output buffer
 | 
					 * @param len length of out_buf in bytes
 | 
				
			||||||
 * @param pixelstride pixel stride of input buffer
 | 
					 * @param pixelstride pixel stride of input buffer
 | 
				
			||||||
 * @return size of output in bytes, -1 if buffer overflows
 | 
					 * @return size of output in bytes, -1 if buffer overflows
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int expand_rle_row(SgiState *s, uint8_t *out_buf,
 | 
					static int expand_rle_row(SgiState *s, uint8_t *out_buf,
 | 
				
			||||||
                          uint8_t *out_end, int pixelstride)
 | 
					                          int len, int pixelstride)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    unsigned char pixel, count;
 | 
					    unsigned char pixel, count;
 | 
				
			||||||
    unsigned char *orig = out_buf;
 | 
					    unsigned char *orig = out_buf;
 | 
				
			||||||
@@ -58,7 +59,10 @@ static int expand_rle_row(SgiState *s, uint8_t *out_buf,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Check for buffer overflow. */
 | 
					        /* Check for buffer overflow. */
 | 
				
			||||||
        if(out_buf + pixelstride * count >= out_end) return -1;
 | 
					        if (pixelstride * (count - 1) >= len) {
 | 
				
			||||||
 | 
					            av_log(s->avctx, AV_LOG_ERROR, "Invalid pixel count.\n");
 | 
				
			||||||
 | 
					            return AVERROR_INVALIDDATA;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (pixel & 0x80) {
 | 
					        if (pixel & 0x80) {
 | 
				
			||||||
            while (count--) {
 | 
					            while (count--) {
 | 
				
			||||||
@@ -101,7 +105,7 @@ static int read_rle_sgi(uint8_t *out_buf, SgiState *s)
 | 
				
			|||||||
            dest_row -= s->linesize;
 | 
					            dest_row -= s->linesize;
 | 
				
			||||||
            start_offset = bytestream2_get_be32(&g_table);
 | 
					            start_offset = bytestream2_get_be32(&g_table);
 | 
				
			||||||
            bytestream2_seek(&s->g, start_offset, SEEK_SET);
 | 
					            bytestream2_seek(&s->g, start_offset, SEEK_SET);
 | 
				
			||||||
            if (expand_rle_row(s, dest_row + z, dest_row + FFABS(s->linesize),
 | 
					            if (expand_rle_row(s, dest_row + z, FFABS(s->linesize) - z,
 | 
				
			||||||
                               s->depth) != s->width) {
 | 
					                               s->depth) != s->width) {
 | 
				
			||||||
                return AVERROR_INVALIDDATA;
 | 
					                return AVERROR_INVALIDDATA;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -259,6 +263,15 @@ static av_cold int sgi_end(AVCodecContext *avctx)
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static av_cold int sgi_decode_init(AVCodecContext *avctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SgiState *s = avctx->priv_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s->avctx = avctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AVCodec ff_sgi_decoder = {
 | 
					AVCodec ff_sgi_decoder = {
 | 
				
			||||||
    .name           = "sgi",
 | 
					    .name           = "sgi",
 | 
				
			||||||
    .type           = AVMEDIA_TYPE_VIDEO,
 | 
					    .type           = AVMEDIA_TYPE_VIDEO,
 | 
				
			||||||
@@ -267,6 +280,7 @@ AVCodec ff_sgi_decoder = {
 | 
				
			|||||||
    .init           = sgi_init,
 | 
					    .init           = sgi_init,
 | 
				
			||||||
    .close          = sgi_end,
 | 
					    .close          = sgi_end,
 | 
				
			||||||
    .decode         = decode_frame,
 | 
					    .decode         = decode_frame,
 | 
				
			||||||
 | 
					    .init           = sgi_decode_init,
 | 
				
			||||||
    .long_name      = NULL_IF_CONFIG_SMALL("SGI image"),
 | 
					    .long_name      = NULL_IF_CONFIG_SMALL("SGI image"),
 | 
				
			||||||
    .capabilities   = CODEC_CAP_DR1,
 | 
					    .capabilities   = CODEC_CAP_DR1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user