diff options
author | wm4 <wm4@nowhere> | 2019-01-04 12:23:14 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2019-09-19 20:37:03 +0200 |
commit | 8ca438636682b90de807dd1c46ad18cfab950c4b (patch) | |
tree | 039e5837aec0bc9f6eac2256d6756c7e498555c0 | |
parent | e5c1cf2e3e76deb32532d213d9b6a48a2b7cf242 (diff) | |
download | mpv-8ca438636682b90de807dd1c46ad18cfab950c4b.tar.bz2 mpv-8ca438636682b90de807dd1c46ad18cfab950c4b.tar.xz |
stream_libarchive: fix another crash with broken rar files
libarchive (sometimes affectionately called libcve) has this annoying
behavior that if after a "fatal" error, you do any operation on the
archive context other than querying the error and closing the context,
you get a free CVE. So we close the archive context in these situations.
This can set p->mpa to NULL, so code accessing this field needs to be
careful.
This was not considered in a certain code path, and a simple truncated
.rar file made it crash. Part of the problem was that the file inside
the rar was a mkv file, which triggered seeking when the demux_mkv
resync code encountered bogus data.
This is probably a regression from a relatively recent change to this
code (in any case mpv 0.29.1 doesn't crash).
Fix this by adding the check.
There's also a mechanism to reopen an archive context used to emulate
seeking, since most libarchive format handlers don't support this
natively. Add a reopen call to the codepath, because obviously it should
always be possible to seek back into a "working" area of the file.
There is a second bug with this: if reopening fails, we don't adjust the
current position back to 0, which in some cases means we accidentally
return bogus data to the reader when we shouldn't. Fix this by always
resetting the position on reopening.
-rw-r--r-- | stream/stream_libarchive.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/stream/stream_libarchive.c b/stream/stream_libarchive.c index ae06efb890..54ebc64b98 100644 --- a/stream/stream_libarchive.c +++ b/stream/stream_libarchive.c @@ -361,6 +361,7 @@ static int reopen_archive(stream_t *s) { struct priv *p = s->priv; mp_archive_free(p->mpa); + s->pos = 0; p->mpa = mp_archive_new(s->log, p->src, MP_ARCHIVE_FLAG_UNSAFE); if (!p->mpa) return STREAM_ERROR; @@ -423,9 +424,10 @@ static int archive_entry_seek(stream_t *s, int64_t newpos) MP_VERBOSE(s, "trying to reopen archive for performing seek\n"); if (reopen_archive(s) < STREAM_OK) return -1; - s->pos = 0; } if (newpos > s->pos) { + if (!p->mpa && reopen_archive(s) < STREAM_OK) + return -1; // For seeking forwards, just keep reading data (there's no libarchive // skip function either). char buffer[4096]; |