Fix for CFH detect in ZipArchiveInputStream

The problem has been fixed in commit 86bb35a. This commit just add a
test for it, and document it in changes.xml.
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c55b876..13c8b5d 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -236,6 +236,12 @@
         Github Pull Request #127.
       </action>
       <action type="update" due-to="Dependabot" date="2020-09-08">Update actions/setup-java from v1.4.1 to v1.4.2 #133.</action>
+      <action type="fix" date="2020-09-24" dev="PeterLee">
+        Fix for the CFH signature detect in ZipArchiveInputStream.
+        The problem could be reproduced by a zip archive with Data
+        Descriptor and STORED, and without the Data Descriptor
+        signature.
+      </action>
     </release>
     <release version="1.20" date="2020-02-08"
              description="Release 1.20 (Java 7)">
diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java
index 9175476..c1112bc 100644
--- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStreamTest.java
@@ -29,6 +29,7 @@
 
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.EOFException;
 import java.io.File;
 import java.io.FileInputStream;
@@ -37,6 +38,7 @@
 import java.nio.channels.Channels;
 import java.nio.channels.SeekableByteChannel;
 import java.util.Arrays;
+import java.util.zip.ZipEntry;
 import java.util.zip.ZipException;
 
 import org.apache.commons.compress.archivers.ArchiveEntry;
@@ -728,6 +730,15 @@
         }
     }
 
+    @Test
+    public void testZipUsingStoredWithDDAndNoDDSignature() throws IOException {
+        try (InputStream inputStream = forgeZipInputStream();
+             ZipArchiveInputStream zipInputStream = new ZipArchiveInputStream(inputStream, "UTF-8", true, true);) {
+            while (zipInputStream.getNextZipEntry() != null) {
+            }
+        }
+    }
+
     private static byte[] readEntry(final ZipArchiveInputStream zip, final ZipArchiveEntry zae) throws IOException {
         final int len = (int)zae.getSize();
         final byte[] buff = new byte[len];
@@ -764,4 +775,43 @@
             IOUtils.toByteArray(ais);
         }
     }
+
+    /**
+     * Forge a zip archive in memory, using STORED and
+     * Data Descriptor, and without signature of Data
+     * Descriptor.
+     *
+     * @return the input stream of the generated zip
+     * @throws IOException there are problems
+     */
+    private InputStream forgeZipInputStream() throws IOException {
+        try (final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+             final ZipArchiveOutputStream zo = new ZipArchiveOutputStream(byteArrayOutputStream);){
+
+            final ZipArchiveEntry entryA = new ZipArchiveEntry("foo");
+            entryA.setMethod(ZipEntry.STORED);
+            entryA.setSize(4);
+            entryA.setCrc(0xb63cfbcdl);
+            zo.putArchiveEntry(entryA);
+            zo.write(new byte[] { 1, 2, 3, 4 });
+            zo.closeArchiveEntry();
+            zo.close();
+
+            final byte[] zipContent = byteArrayOutputStream.toByteArray();
+            final byte[] old = Arrays.copyOf(zipContent, zipContent.length);
+
+            final byte[] zipContentWithDataDescriptor = new byte[zipContent.length + 12];
+            System.arraycopy(zipContent, 0, zipContentWithDataDescriptor, 0, 37);
+            // modify the general purpose bit flag
+            zipContentWithDataDescriptor[6] = 8;
+
+            // copy the crc-32, compressed size and uncompressed size to the data descriptor
+            System.arraycopy(zipContent, 14, zipContentWithDataDescriptor, 37, 12);
+
+            // and copy the rest of the zip content
+            System.arraycopy(zipContent, 37, zipContentWithDataDescriptor, 49, zipContent.length - 37);
+
+            return new ByteArrayInputStream(zipContentWithDataDescriptor);
+        }
+    }
 }