Issue #27517: LZMA compressor and decompressor no longer raise exceptions if
given empty data twice.  Patch by Benjamin Fogle.
diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py
index fdc8e11..d7a8576 100644
--- a/Lib/test/test_lzma.py
+++ b/Lib/test/test_lzma.py
@@ -137,6 +137,21 @@
         self.assertTrue(lzd.eof)
         self.assertEqual(lzd.unused_data, b"")
 
+    def test_decompressor_chunks_empty(self):
+        lzd = LZMADecompressor()
+        out = []
+        for i in range(0, len(COMPRESSED_XZ), 10):
+            self.assertFalse(lzd.eof)
+            out.append(lzd.decompress(b''))
+            out.append(lzd.decompress(b''))
+            out.append(lzd.decompress(b''))
+            out.append(lzd.decompress(COMPRESSED_XZ[i:i+10]))
+        out = b"".join(out)
+        self.assertEqual(out, INPUT)
+        self.assertEqual(lzd.check, lzma.CHECK_CRC64)
+        self.assertTrue(lzd.eof)
+        self.assertEqual(lzd.unused_data, b"")
+
     def test_decompressor_chunks_maxsize(self):
         lzd = LZMADecompressor()
         max_length = 100
@@ -274,6 +289,16 @@
         lzd = LZMADecompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4)
         self._test_decompressor(lzd, cdata, lzma.CHECK_NONE)
 
+    def test_roundtrip_raw_empty(self):
+        lzc = LZMACompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4)
+        cdata = lzc.compress(INPUT)
+        cdata += lzc.compress(b'')
+        cdata += lzc.compress(b'')
+        cdata += lzc.compress(b'')
+        cdata += lzc.flush()
+        lzd = LZMADecompressor(lzma.FORMAT_RAW, filters=FILTERS_RAW_4)
+        self._test_decompressor(lzd, cdata, lzma.CHECK_NONE)
+
     def test_roundtrip_chunks(self):
         lzc = LZMACompressor()
         cdata = []
@@ -284,6 +309,19 @@
         lzd = LZMADecompressor()
         self._test_decompressor(lzd, cdata, lzma.CHECK_CRC64)
 
+    def test_roundtrip_empty_chunks(self):
+        lzc = LZMACompressor()
+        cdata = []
+        for i in range(0, len(INPUT), 10):
+            cdata.append(lzc.compress(INPUT[i:i+10]))
+            cdata.append(lzc.compress(b''))
+            cdata.append(lzc.compress(b''))
+            cdata.append(lzc.compress(b''))
+        cdata.append(lzc.flush())
+        cdata = b"".join(cdata)
+        lzd = LZMADecompressor()
+        self._test_decompressor(lzd, cdata, lzma.CHECK_CRC64)
+
     # LZMADecompressor intentionally does not handle concatenated streams.
 
     def test_decompressor_multistream(self):
diff --git a/Misc/ACKS b/Misc/ACKS
index 7711152..0cf1802 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -452,6 +452,7 @@
 Tom Flanagan
 Matt Fleming
 Hernán Martínez Foffani
+Benjamin Fogle
 Artem Fokin
 Arnaud Fontaine
 Michael Foord
diff --git a/Misc/NEWS b/Misc/NEWS
index 2d832a7..a621be3 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -30,6 +30,9 @@
 Library
 -------
 
+- Issue #27517: LZMA compressor and decompressor no longer raise exceptions if
+  given empty data twice.  Patch by Benjamin Fogle.
+
 - Issue #28549: Fixed segfault in curses's addch() with ncurses6.
 
 - Issue #28449: tarfile.open() with mode "r" or "r:" now tries to open a tar
diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c
index f5dcea1..bb77552 100644
--- a/Modules/_lzmamodule.c
+++ b/Modules/_lzmamodule.c
@@ -521,6 +521,8 @@
         Py_BEGIN_ALLOW_THREADS
         lzret = lzma_code(&c->lzs, action);
         data_size = (char *)c->lzs.next_out - PyBytes_AS_STRING(result);
+        if (lzret == LZMA_BUF_ERROR && len == 0 && c->lzs.avail_out > 0)
+            lzret = LZMA_OK; /* That wasn't a real error */
         Py_END_ALLOW_THREADS
         if (catch_lzma_error(lzret))
             goto error;
@@ -896,6 +898,9 @@
     PyObject *result;
     lzma_stream *lzs = &d->lzs;
 
+    if (lzs->avail_in == 0)
+        return PyBytes_FromStringAndSize(NULL, 0);
+
     if (max_length < 0 || max_length >= INITIAL_BUFFER_SIZE)
         result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE);
     else