Extract: Parse Unicode Path Extra field in minizip

Adds parsing of the Info-ZIP Extra field which overrides the
file name in the File Header only if the CRC in the extra field
is a CRC of the file name in the File Header.

See https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
section 4.6.9 for reference.

Also tidied up some whitespace indent.

Bug: 953256, 953599
Tests: Manually tested, auto test in follow on CL
Change-Id: I1283dcb88a203c3bb56c1d9c504035a2e51aecbd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3641742
Reviewed-by: Noel Gordon <noel@chromium.org>
Commit-Queue: Alex Danilo <adanilo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1002476}
NOKEYCHECK=True
GitOrigin-RevId: c8834821f452a3d424edd0ed2a1e9ceeda38d0ea
diff --git a/contrib/minizip/README.chromium b/contrib/minizip/README.chromium
new file mode 100644
index 0000000..4f7951f
--- /dev/null
+++ b/contrib/minizip/README.chromium
@@ -0,0 +1,15 @@
+Name: ZIP file API for reading file entries in a ZIP archive
+Short Name: minizip
+URL: https://github.com/madler/zlib/tree/master/contrib/minizip
+Version: 1.2.12
+License: Zlib
+Security Critical: yes
+
+Description:
+Minizip provides API on top of zlib that can enumerate and extract ZIP archive
+files. See minizip.md for chromium build instructions.
+
+Local Modifications:
+- Add parsing of the 'Info-ZIP Unicode Path Extra Field' as described in
+  https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT section 4.6.9.
+  (see crrev.com/3641742)
diff --git a/contrib/minizip/unzip.c b/contrib/minizip/unzip.c
index e8b2bc5..0a1d8b4 100644
--- a/contrib/minizip/unzip.c
+++ b/contrib/minizip/unzip.c
@@ -1023,46 +1023,102 @@
         while(acc < file_info.size_file_extra)
         {
             uLong headerId;
-                                                uLong dataSize;
+            uLong dataSize;
 
             if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
                 err=UNZ_ERRNO;
 
             if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
                 err=UNZ_ERRNO;
-
+            
             /* ZIP64 extra fields */
             if (headerId == 0x0001)
             {
-                                                        uLong uL;
+                uLong uL;
 
-                                                                if(file_info.uncompressed_size == MAXU32)
-                                                                {
-                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
-                                                                                        err=UNZ_ERRNO;
-                                                                }
+                if(file_info.uncompressed_size == MAXU32)
+                {
+                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+                        err=UNZ_ERRNO;
+                }
 
-                                                                if(file_info.compressed_size == MAXU32)
-                                                                {
-                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
-                                                                                  err=UNZ_ERRNO;
-                                                                }
+                if(file_info.compressed_size == MAXU32)
+                {
+                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+                        err=UNZ_ERRNO;
+                }
 
-                                                                if(file_info_internal.offset_curfile == MAXU32)
-                                                                {
-                                                                        /* Relative Header offset */
-                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
-                                                                                err=UNZ_ERRNO;
-                                                                }
+                if(file_info_internal.offset_curfile == MAXU32)
+                {
+                    /* Relative Header offset */
+                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+                        err=UNZ_ERRNO;
+                }
 
-                                                                if(file_info.disk_num_start == MAXU32)
-                                                                {
-                                                                        /* Disk Start Number */
-                                                                        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
-                                                                                err=UNZ_ERRNO;
-                                                                }
+                if(file_info.disk_num_start == MAXU32)
+                {
+                    /* Disk Start Number */
+                    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+                        err=UNZ_ERRNO;
+                }
 
             }
+            else if (headerId == 0x7075) /* Info-ZIP Unicode Path Extra Field */
+            {
+                int version = 0;
+
+                if (unz64local_getByte(&s->z_filefunc, s->filestream, &version) != UNZ_OK)
+                {
+                    err = UNZ_ERRNO;
+                }
+                if (version != 1)
+                {
+                    if (ZSEEK64(s->z_filefunc, s->filestream,dataSize - 1, ZLIB_FILEFUNC_SEEK_CUR) != 0)
+                    {
+                        err = UNZ_ERRNO;
+                    }
+                }
+                else
+                {
+                    uLong uCrc, uHeaderCrc, fileNameSize;
+
+                    if (unz64local_getLong(&s->z_filefunc, s->filestream, &uCrc) != UNZ_OK)
+                    {
+                        err = UNZ_ERRNO;
+                    }
+                    uHeaderCrc = crc32(0, (const unsigned char *)szFileName, file_info.size_filename);
+                    fileNameSize = dataSize - (2 * sizeof (short) + 1);
+                    /* Check CRC against file name in the header. */
+                    if (uHeaderCrc != uCrc)
+                    {
+                        if (ZSEEK64(s->z_filefunc, s->filestream, fileNameSize, ZLIB_FILEFUNC_SEEK_CUR) != 0)
+                        {
+                            err = UNZ_ERRNO;
+                        }
+                    }
+                    else
+                    {
+                        uLong uSizeRead;
+
+                        if (fileNameSize < fileNameBufferSize)
+                        {
+                             *(szFileName + fileNameSize) = '\0';
+                            uSizeRead = fileNameSize;
+                        }
+                        else
+                        {
+                            uSizeRead = fileNameBufferSize;
+                        }
+                        if ((fileNameSize > 0) && (fileNameBufferSize > 0))
+                        {
+                            if (ZREAD64(s->z_filefunc, s->filestream, szFileName, uSizeRead) != uSizeRead)
+                            {
+                                err = UNZ_ERRNO;
+                            }
+                        }
+                    }
+                }
+            }
             else
             {
                 if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)