From 9e6c4f8d80c4c7b0af9b728fe7c710784534026c Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Fri, 4 Sep 2020 17:53:47 +0200
Subject: [PATCH] archive/bzip2: throw on unexpected input EOF

Don't silently return 0 when there is no more data, because this may
crash the caller.  And flush output even if input EOF has been reached.
---
 NEWS                                       | 2 ++
 src/archive/plugins/Bzip2ArchivePlugin.cxx | 6 ++++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index 96a3c40bf..bbfbb271f 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ ver 0.21.26 (not yet released)
   - osx: fix crash bug
   - sles: support floating point samples
 * archive
+  - bzip2: fix crash on corrupt bzip2 file
+  - bzip2: flush output at end of input file
   - zzip: fix crash on corrupt ZIP file
 * decoder
   - sndfile: fix lost samples at end of file
diff --git a/src/archive/plugins/Bzip2ArchivePlugin.cxx b/src/archive/plugins/Bzip2ArchivePlugin.cxx
index 493ffec88..0228fa743 100644
--- a/src/archive/plugins/Bzip2ArchivePlugin.cxx
+++ b/src/archive/plugins/Bzip2ArchivePlugin.cxx
@@ -148,8 +148,7 @@ Bzip2InputStream::Read(void *ptr, size_t length)
 	bzstream.avail_out = length;
 
 	do {
-		if (!FillBuffer())
-			return 0;
+		const bool had_input = FillBuffer();
 
 		bz_result = BZ2_bzDecompress(&bzstream);
 
@@ -160,6 +159,9 @@ Bzip2InputStream::Read(void *ptr, size_t length)
 
 		if (bz_result != BZ_OK)
 			throw std::runtime_error("BZ2_bzDecompress() has failed");
+
+		if (!had_input && bzstream.avail_out == length)
+			throw std::runtime_error("Unexpected end of bzip2 file");
 	} while (bzstream.avail_out == length);
 
 	nbytes = length - bzstream.avail_out;