You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
avformat/jpegxl_anim_dec: avoid overrun with jxlp boxes in container
This switches the jpegxl_collect_codestream_header function to use avcodec/bytestream2, which better enforces barriers, and should avoid overrunning buffers with jxlp boxes if the size is zero or if the size is so small the box is invalid. Signed-off-by: Leo Izen <leo.izen@gmail.com>
This commit is contained in:
@@ -28,6 +28,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "libavcodec/bytestream.h"
|
||||||
#define BITSTREAM_READER_LE
|
#define BITSTREAM_READER_LE
|
||||||
#include "libavcodec/get_bits.h"
|
#include "libavcodec/get_bits.h"
|
||||||
|
|
||||||
@@ -48,62 +49,65 @@ typedef struct JXLAnimDemuxContext {
|
|||||||
* returns the number of bytes consumed from input, may be greater than input_len
|
* returns the number of bytes consumed from input, may be greater than input_len
|
||||||
* if the input doesn't end on an ISOBMFF-box boundary
|
* if the input doesn't end on an ISOBMFF-box boundary
|
||||||
*/
|
*/
|
||||||
static int jpegxl_collect_codestream_header(const uint8_t *input_buffer, int input_len, uint8_t *buffer, int buflen, int *copied) {
|
static int jpegxl_collect_codestream_header(const uint8_t *input_buffer, int input_len,
|
||||||
const uint8_t *b = input_buffer;
|
uint8_t *buffer, int buflen, int *copied) {
|
||||||
|
GetByteContext gb;
|
||||||
*copied = 0;
|
*copied = 0;
|
||||||
|
bytestream2_init(&gb, input_buffer, input_len);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
int head_size = 8;
|
int head_size = 8;
|
||||||
|
|
||||||
if (b - input_buffer >= input_len - 16)
|
if (bytestream2_get_bytes_left(&gb) < 16)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
size = AV_RB32(b);
|
size = bytestream2_get_be32(&gb);
|
||||||
b += 4;
|
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
size = AV_RB64(b);
|
size = bytestream2_get_be64(&gb);
|
||||||
b += 8;
|
|
||||||
head_size = 16;
|
head_size = 16;
|
||||||
}
|
}
|
||||||
/* invalid ISOBMFF size */
|
/* invalid ISOBMFF size */
|
||||||
if (size > 0 && size <= head_size)
|
if (size && size <= head_size)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
if (size > 0)
|
if (size)
|
||||||
size -= head_size;
|
size -= head_size;
|
||||||
|
|
||||||
tag = AV_RL32(b);
|
tag = bytestream2_get_le32(&gb);
|
||||||
b += 4;
|
|
||||||
if (tag == MKTAG('j', 'x', 'l', 'p')) {
|
if (tag == MKTAG('j', 'x', 'l', 'p')) {
|
||||||
b += 4;
|
if (bytestream2_get_bytes_left(&gb) < 4)
|
||||||
size -= 4;
|
break;
|
||||||
|
bytestream2_skip(&gb, 4);
|
||||||
|
if (size) {
|
||||||
|
if (size <= 4)
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
size -= 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* size = 0 means "until EOF". this is legal but uncommon
|
||||||
|
* here we just set it to the remaining size of the probe buffer
|
||||||
|
*/
|
||||||
|
if (!size)
|
||||||
|
size = bytestream2_get_bytes_left(&gb);
|
||||||
|
|
||||||
if (tag == MKTAG('j', 'x', 'l', 'c') || tag == MKTAG('j', 'x', 'l', 'p')) {
|
if (tag == MKTAG('j', 'x', 'l', 'c') || tag == MKTAG('j', 'x', 'l', 'p')) {
|
||||||
/*
|
|
||||||
* size = 0 means "until EOF". this is legal but uncommon
|
|
||||||
* here we just set it to the remaining size of the probe buffer
|
|
||||||
* which at this point should always be nonnegative
|
|
||||||
*/
|
|
||||||
if (size == 0 || size > input_len - (b - input_buffer))
|
|
||||||
size = input_len - (b - input_buffer);
|
|
||||||
|
|
||||||
if (size > buflen - *copied)
|
if (size > buflen - *copied)
|
||||||
size = buflen - *copied;
|
size = buflen - *copied;
|
||||||
/*
|
/*
|
||||||
* arbitrary chunking of the payload makes this memcpy hard to avoid
|
* arbitrary chunking of the payload makes this memcpy hard to avoid
|
||||||
* in practice this will only be performed one or two times at most
|
* in practice this will only be performed one or two times at most
|
||||||
*/
|
*/
|
||||||
memcpy(buffer + *copied, b, size);
|
*copied += bytestream2_get_buffer(&gb, buffer + *copied, size);
|
||||||
*copied += size;
|
} else {
|
||||||
|
bytestream2_skip(&gb, size);
|
||||||
}
|
}
|
||||||
b += size;
|
if (bytestream2_get_bytes_left(&gb) <= 0 || *copied >= buflen)
|
||||||
if (b >= input_buffer + input_len || *copied >= buflen)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return b - input_buffer;
|
return bytestream2_tell(&gb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jpegxl_anim_probe(const AVProbeData *p)
|
static int jpegxl_anim_probe(const AVProbeData *p)
|
||||||
|
Reference in New Issue
Block a user