From 8b4ca868d1f566d1b19ecbbb2766d0031a6cc4a9 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Mon, 29 Apr 2024 20:26:17 +0100 Subject: [PATCH] filehandle: Add missing avio_read error check Rather than return an error when reading fails part way though, avio_read returns those bytes and fails on the *next* read. This can cause weird stuff to happen, like calculating wrong file signatures due to partial reads, when used over a network. To figure out if there was a partial read due to an error, we need to check avio_feof, which for some reason not only checks for EOF but also for all read/write errors, by its own docs. This only tells us *if* there was an error, or EOF, though, so we must also check the contents of avio->error after that. Signed-off-by: Derek Buitenhuis --- src/core/filehandle.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/core/filehandle.cpp b/src/core/filehandle.cpp index 7c7dcd5507..a909f6357e 100644 --- a/src/core/filehandle.cpp +++ b/src/core/filehandle.cpp @@ -73,9 +73,16 @@ int64_t FileHandle::Tell() { size_t FileHandle::Read(char *buffer, size_t size) { int count = avio_read(avio, (unsigned char *)buffer, size); - if (count < 0) + if (count < 0) { throw FFMS_Exception(error_source, FFMS_ERROR_FILE_READ, "Failed to read from '" + filename + "': " + AVErrorToString(count)); + } else if (avio_feof(avio)) { + // "Similar to feof() but also returns nonzero on read errors" -- FFmpeg docs + if (avio->error != 0 && avio->error != AVERROR_EOF) { + throw FFMS_Exception(error_source, FFMS_ERROR_FILE_READ, + "Failed to read from '" + filename + "': " + AVErrorToString(avio->error)); + } + } return (size_t)count; }