From: Mike Frysinger Date: Fri, 17 May 2019 10:53:18 +0000 (+1200) Subject: zip: check filename crc in Info-ZIP Unicode Path Extra Field X-Git-Tag: v3.4.0~18^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1201%2Fhead;p=thirdparty%2Flibarchive.git zip: check filename crc in Info-ZIP Unicode Path Extra Field The 0x7075 extension includes a crc of the filename that's in the CDE to make sure that the UTF8 string is always up to date. If an older tool updates the CDE but doesn't update the 0x7075 field, we want to ignore the UTF8 string since it's stale. --- diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index c6a3cf943..1fa98fb76 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -755,6 +755,23 @@ process_extra(struct archive_read *a, struct archive_entry *entry, break; } + /* Make sure the CRC32 of the filename matches. */ + if (!zip->ignore_crc32) { + const char *cp = archive_entry_pathname(entry); + if (cp) { + unsigned long file_crc = zip->crc32func(0, cp, strlen(cp)); + unsigned long utf_crc = archive_le32dec(p + offset - 4); + if (file_crc != utf_crc) { +#ifdef DEBUG + fprintf(stderr, "CRC filename mismatch; CDE is %lx, " + "but UTF8 is outdated with %lx\n", + file_crc, utf_crc); +#endif + break; + } + } + } + if (archive_entry_copy_pathname_l(entry, p + offset, datasize, zip->sconv_utf8) != 0) { /* Ignore the error, and fallback to the path diff --git a/libarchive/test/test_read_format_zip_7075_utf8_paths.c b/libarchive/test/test_read_format_zip_7075_utf8_paths.c index 85c44c0ed..7b78770aa 100644 --- a/libarchive/test/test_read_format_zip_7075_utf8_paths.c +++ b/libarchive/test/test_read_format_zip_7075_utf8_paths.c @@ -58,15 +58,10 @@ verify(struct archive *a) { assertEqualUTF8String(p, "File 3 - \xC3\xA4.txt"); #endif + /* The CRC of the filename fails, so fall back to CDE. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assert((p = archive_entry_pathname_utf8(ae)) != NULL); -#if defined(__APPLE__) - /* Compare NFD string. */ - assertEqualUTF8String(p, "File 4 - a\xCC\x8A.txt"); -#else - /* Compare NFC string. */ - assertEqualUTF8String(p, "File 4 - \xC3\xA5.txt"); -#endif + assertEqualUTF8String(p, "File 4 - xx.txt"); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); } diff --git a/libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu b/libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu index 65c34f517..332f99689 100644 --- a/libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu +++ b/libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu @@ -1,18 +1,18 @@ begin 644 test_read_format_zip_7075_utf8_paths.zip M4$L#!!0````(`,$^9D5BZ95P"P````D````*````1FEL92`Q+G1X=`M)+2Y1 M2,O,204`4$L#!!0````(`,$^9D5BZ95P"P````D````/`!@`1FEL92`R("T@ -M>'@N='AT=7`4``'W!4IU1FEL92`R("T@P[8N='AT"TDM+E%(R\Q)!0!02P,$ +M>'@N='AT=7`4``$NSPQQ1FEL92`R("T@P[8N='AT"TDM+E%(R\Q)!0!02P,$ M%`````@`P3YF16+IE7`+````"0````\`&`!&:6QE(#,@+2!X>"YT>'1U'0+22TN44C+S$D%`%!+`P04````"`#!/F9% +M`1"DSIY&:6QE(#,@+2##I"YT>'0+22TN44C+S$D%`%!+`P04````"`#!/F9% M8NF5<`L````)````#P`8`$9I;&4@-"`M('AX+G1X='5P%``!G[AP'$9I;&4@ M-"`M(,.E+G1X=`M)+2Y12,O,204`4$L!`A\`%`````@`P3YF16+IE7`+```` M"0````H`)``````````@`````````$9I;&4@,2YT>'0*`"````````$`&``Q M6UASCOG/`5^OQVV.^<\!7Z_';8[YSP%02P$"'P`4````"`#!/F9%8NF5<`L` M```)````#@`\`````````"`````S````1FEL92`R("T@E"YT>'0*`"`````` -M``$`&``Q6UASCOG/`2M.B72.^<\!*TZ)=([YSP%U'102P$"'P`4````"`#!/F9%8NF5<`L````)````#@`\```````` M`"````"#````1FEL92`S("T@A"YT>'0*`"````````$`&``Q6UASCOG/`5<$ -M&W>.^<\!5P0;=X[YSP%U'102P$"'P`4 +M&W>.^<\!5P0;=X[YSP%U'102P$"'P`4 M````"`#!/F9%8NF5<`L````)````#@`\`````````"````#3````1FEL92`T M("T@ABYT>'0*`"````````$`&``Q6UASCOG/`6#)ZG:.^<\!8,GJ=H[YSP%U M'102P4&``````0`!`#$`0``(P$`````