mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-21 15:00:27 +00:00
avformat/webpenc: Fix memleak when using invalid packets
The WebP muxer sometimes caches a packet it receives to write it later; yet if a cached packet is too small (so small as to be invalid), it is cached, but not written and not unreferenced. Such a packet leaks, either by being overwritten by the next packet or because it is never unreferenced at all. Fix this by not caching unusable packets at all; and error out on invalid packets. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
This commit is contained in:
parent
484a322f0a
commit
f9043de99a
@ -53,24 +53,22 @@ static int webp_init(AVFormatContext *s)
|
|||||||
|
|
||||||
static int is_animated_webp_packet(AVPacket *pkt)
|
static int is_animated_webp_packet(AVPacket *pkt)
|
||||||
{
|
{
|
||||||
if (pkt->size) {
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
unsigned flags = 0;
|
unsigned flags = 0;
|
||||||
|
|
||||||
if (pkt->size < 4)
|
if (pkt->size < 4)
|
||||||
return 0;
|
return AVERROR_INVALIDDATA;
|
||||||
if (AV_RL32(pkt->data) == AV_RL32("RIFF"))
|
if (AV_RL32(pkt->data) == AV_RL32("RIFF"))
|
||||||
skip = 12;
|
skip = 12;
|
||||||
|
// Safe to do this as a valid WebP bitstream is >=30 bytes.
|
||||||
if (pkt->size < skip + 4)
|
if (pkt->size < skip + 4)
|
||||||
return 0;
|
return AVERROR_INVALIDDATA;
|
||||||
if (AV_RL32(pkt->data + skip) == AV_RL32("VP8X")) {
|
if (AV_RL32(pkt->data + skip) == AV_RL32("VP8X")) {
|
||||||
flags |= pkt->data[skip + 4 + 4];
|
flags |= pkt->data[skip + 4 + 4];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & 2) // ANIMATION_FLAG is on
|
if (flags & 2) // ANIMATION_FLAG is on
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,13 +82,9 @@ static int flush(AVFormatContext *s, int trailer, int64_t pts)
|
|||||||
unsigned flags = 0;
|
unsigned flags = 0;
|
||||||
int vp8x = 0;
|
int vp8x = 0;
|
||||||
|
|
||||||
if (w->last_pkt.size < 4)
|
|
||||||
return 0;
|
|
||||||
if (AV_RL32(w->last_pkt.data) == AV_RL32("RIFF"))
|
if (AV_RL32(w->last_pkt.data) == AV_RL32("RIFF"))
|
||||||
skip = 12;
|
skip = 12;
|
||||||
|
|
||||||
if (w->last_pkt.size < skip + 4)
|
|
||||||
return 0; // Safe to do this as a valid WebP bitstream is >=30 bytes.
|
|
||||||
if (AV_RL32(w->last_pkt.data + skip) == AV_RL32("VP8X")) {
|
if (AV_RL32(w->last_pkt.data + skip) == AV_RL32("VP8X")) {
|
||||||
flags |= w->last_pkt.data[skip + 4 + 4];
|
flags |= w->last_pkt.data[skip + 4 + 4];
|
||||||
vp8x = 1;
|
vp8x = 1;
|
||||||
@ -149,7 +143,14 @@ static int flush(AVFormatContext *s, int trailer, int64_t pts)
|
|||||||
static int webp_write_packet(AVFormatContext *s, AVPacket *pkt)
|
static int webp_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||||
{
|
{
|
||||||
WebpContext *w = s->priv_data;
|
WebpContext *w = s->priv_data;
|
||||||
w->using_webp_anim_encoder |= is_animated_webp_packet(pkt);
|
int ret;
|
||||||
|
|
||||||
|
if (!pkt->size)
|
||||||
|
return 0;
|
||||||
|
ret = is_animated_webp_packet(pkt);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
w->using_webp_anim_encoder |= ret;
|
||||||
|
|
||||||
if (w->using_webp_anim_encoder) {
|
if (w->using_webp_anim_encoder) {
|
||||||
avio_write(s->pb, pkt->data, pkt->size);
|
avio_write(s->pb, pkt->data, pkt->size);
|
||||||
|
Loading…
Reference in New Issue
Block a user