Apr 28, 2020, 14:05 by mattias.wad...@gmail.com: > On Tue, Apr 28, 2020 at 1:59 PM Lynne <d...@lynne.ee> wrote: > >> >> This makes decoding far more robust, since OggS, the ogg magic, >> can be commonly found randomly in streams, which previously made >> the demuxer think there's a new stream or a change in such. >> >> Patch attached. >> > > Maybe nitpick, could seek back even longer than size on crc mismatch? >
Thanks a lot for reviewing the patches. I was thinking about seeking back further to perhaps the version byte, but unfortunately, that's not possible. If ffio_ensure_seekback is called multiple times, the last call overwrites the previous calls and we lose the ability to seek before it. Since the only place at which we know the exact size of the page is when its signaled, that's the only point we can ensure we can seek back to. Before that, we can seek back from the header's end to the version byte. Unfortunately, that would mean verifying the header before the checksum, which as you've pointed out, is bad for robustness. Still, this is definitely an improvement, since previously the demuxer didn't seek back at all. Anyway, I've implemented checking the version byte after reading the CRC as you suggested and have attached the new patch.
>From 989d02631f2b47f125d3d8a3474572fe25ab1251 Mon Sep 17 00:00:00 2001 From: Lynne <d...@lynne.ee> Date: Tue, 28 Apr 2020 12:52:11 +0100 Subject: [PATCH 2/3] oggdec: verify page checksum This makes decoding far more robust, since OggS, the ogg magic, can be commonly found randomly in streams, which previously made the demuxer think there's a new stream or a change in such. --- libavformat/oggdec.c | 46 ++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 7db26840b2..e0188c7c59 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -31,6 +31,7 @@ #include <stdio.h> #include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" +#include "avio_internal.h" #include "oggdec.h" #include "avformat.h" #include "internal.h" @@ -321,8 +322,9 @@ static int ogg_read_page(AVFormatContext *s, int *sid) int flags, nsegs; uint64_t gp; uint32_t serial; + uint32_t crc, crc_tmp; int size = 0, idx; - int64_t page_pos; + int64_t version, page_pos; uint8_t sync[4]; uint8_t segments[255]; uint8_t *readout_buf; @@ -359,15 +361,19 @@ static int ogg_read_page(AVFormatContext *s, int *sid) return AVERROR_INVALIDDATA; } - if (avio_r8(bc) != 0) { /* version */ - av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n"); - return AVERROR_INVALIDDATA; - } + /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */ + ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f); - flags = avio_r8(bc); - gp = avio_rl64(bc); - serial = avio_rl32(bc); - avio_skip(bc, 8); /* seq, crc */ + version = avio_r8(bc); + flags = avio_r8(bc); + gp = avio_rl64(bc); + serial = avio_rl32(bc); + avio_skip(bc, 4); /* seq */ + + crc_tmp = ffio_get_checksum(bc); + crc = avio_rb32(bc); + crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4); + ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp); nsegs = avio_r8(bc); page_pos = avio_tell(bc) - 27; @@ -376,9 +382,6 @@ static int ogg_read_page(AVFormatContext *s, int *sid) if (ret < nsegs) return ret < 0 ? ret : AVERROR_EOF; - if (avio_feof(bc)) - return AVERROR_EOF; - for (i = 0; i < nsegs; i++) size += segments[i]; @@ -407,6 +410,25 @@ static int ogg_read_page(AVFormatContext *s, int *sid) return ret < 0 ? ret : AVERROR_EOF; } + if (crc ^ ffio_get_checksum(bc)) { + av_log(s, AV_LOG_ERROR, "CRC mismatch!\n"); + if (idx < 0) + av_free(readout_buf); + avio_seek(bc, -size, SEEK_CUR); + return 0; + } + + /* Since we're almost sure its a valid packet, checking the version after + * the checksum lets the demuxer be more tolerant */ + if (version) { + av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n"); + if (idx < 0) + av_free(readout_buf); + avio_seek(bc, -size, SEEK_CUR); + return 0; + } + + /* CRC is correct so we can be 99% sure there's an actual change here */ if (idx < 0) { if (data_packets_seen(ogg)) idx = ogg_replace_stream(s, serial, size); -- 2.26.2
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".