|
7 | 7 | #include <cstddef>
|
8 | 8 | #include <vector>
|
9 | 9 |
|
| 10 | +#include "base/files/file_path.h" |
| 11 | +#include "base/files/scoped_temp_dir.h" |
10 | 12 | #include "compression_utils_portable.h"
|
11 | 13 | #include "gtest.h"
|
| 14 | +#include "third_party/zlib/contrib/minizip/unzip.h" |
| 15 | +#include "third_party/zlib/contrib/minizip/zip.h" |
12 | 16 | #include "zlib.h"
|
13 | 17 |
|
14 | 18 | void TestPayloads(size_t input_size, zlib_internal::WrapperType type) {
|
@@ -1015,3 +1019,122 @@ TEST(ZlibTest, DeflateZFixedCorruption) {
|
1015 | 1019 | memcmp(zFixedCorruptionData, decompressed.data(), decompressed.size()),
|
1016 | 1020 | 0);
|
1017 | 1021 | }
|
| 1022 | + |
| 1023 | +TEST(ZlibTest, ZipFilenameCommentSize) { |
| 1024 | + // Check that minizip rejects zip member filenames or comments longer than |
| 1025 | + // the zip format can represent. |
| 1026 | + |
| 1027 | + base::ScopedTempDir temp_dir; |
| 1028 | + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 1029 | + base::FilePath zip_file = temp_dir.GetPath().AppendASCII("crbug1470539.zip"); |
| 1030 | + |
| 1031 | + zipFile zf = zipOpen(zip_file.AsUTF8Unsafe().c_str(), APPEND_STATUS_CREATE); |
| 1032 | + ASSERT_NE(zf, nullptr); |
| 1033 | + |
| 1034 | + // Adding a member with 2^16 byte filename is okay. |
| 1035 | + std::string long_filename(UINT16_MAX, 'a'); |
| 1036 | + EXPECT_EQ(zipOpenNewFileInZip(zf, long_filename.c_str(), nullptr, nullptr, 0, |
| 1037 | + nullptr, 0, nullptr, Z_DEFLATED, |
| 1038 | + Z_DEFAULT_COMPRESSION), |
| 1039 | + ZIP_OK); |
| 1040 | + EXPECT_EQ(zipWriteInFileInZip(zf, "1", 1), ZIP_OK); |
| 1041 | + EXPECT_EQ(zipCloseFileInZip(zf), ZIP_OK); |
| 1042 | + |
| 1043 | + // Adding a member with 2^16+1 byte filename is NOT okay. |
| 1044 | + std::string too_long_filename = long_filename + 'a'; |
| 1045 | + EXPECT_EQ(zipOpenNewFileInZip(zf, too_long_filename.c_str(), nullptr, nullptr, |
| 1046 | + 0, nullptr, 0, nullptr, Z_DEFLATED, |
| 1047 | + Z_DEFAULT_COMPRESSION), |
| 1048 | + ZIP_PARAMERROR); |
| 1049 | + |
| 1050 | + // Adding a member with 2^16 byte comment is okay. |
| 1051 | + std::string long_comment(UINT16_MAX, 'x'); |
| 1052 | + EXPECT_EQ(zipOpenNewFileInZip(zf, "x", nullptr, nullptr, 0, nullptr, 0, |
| 1053 | + long_comment.c_str(), Z_DEFLATED, |
| 1054 | + Z_DEFAULT_COMPRESSION), |
| 1055 | + ZIP_OK); |
| 1056 | + EXPECT_EQ(zipCloseFileInZip(zf), ZIP_OK); |
| 1057 | + |
| 1058 | + // Adding a member with 2^16+1 byte comment is NOT okay. |
| 1059 | + std::string too_long_comment = long_comment + 'x'; |
| 1060 | + EXPECT_EQ(zipOpenNewFileInZip(zf, "x", nullptr, nullptr, 0, nullptr, 0, |
| 1061 | + too_long_comment.c_str(), Z_DEFLATED, |
| 1062 | + Z_DEFAULT_COMPRESSION), |
| 1063 | + ZIP_PARAMERROR); |
| 1064 | + |
| 1065 | + EXPECT_EQ(zipClose(zf, nullptr), ZIP_OK); |
| 1066 | + |
| 1067 | + // Check that the long filename and comment members were successfully added. |
| 1068 | + unzFile uzf = unzOpen(zip_file.AsUTF8Unsafe().c_str()); |
| 1069 | + ASSERT_NE(uzf, nullptr); |
| 1070 | + char buf[UINT16_MAX + 2]; |
| 1071 | + |
| 1072 | + ASSERT_EQ(unzGoToFirstFile(uzf), UNZ_OK); |
| 1073 | + ASSERT_EQ(unzGetCurrentFileInfo(uzf, nullptr, buf, sizeof(buf), nullptr, 0, |
| 1074 | + nullptr, 0), |
| 1075 | + UNZ_OK); |
| 1076 | + EXPECT_EQ(std::string(buf), long_filename); |
| 1077 | + |
| 1078 | + ASSERT_EQ(unzGoToNextFile(uzf), UNZ_OK); |
| 1079 | + ASSERT_EQ(unzGetCurrentFileInfo(uzf, nullptr, nullptr, 0, nullptr, 0, buf, |
| 1080 | + sizeof(buf)), |
| 1081 | + UNZ_OK); |
| 1082 | + EXPECT_EQ(std::string(buf), long_comment); |
| 1083 | + |
| 1084 | + EXPECT_EQ(unzGoToNextFile(uzf), UNZ_END_OF_LIST_OF_FILE); |
| 1085 | + EXPECT_EQ(unzClose(uzf), UNZ_OK); |
| 1086 | +} |
| 1087 | + |
| 1088 | +TEST(ZlibTest, ZipExtraFieldSize) { |
| 1089 | + // Check that minizip rejects zip members with too large extra fields. |
| 1090 | + |
| 1091 | + std::string extra_field; |
| 1092 | + extra_field.append("\x12\x34"); // Header ID. |
| 1093 | + extra_field.append("\xfb\xff"); // Data size (not including the header). |
| 1094 | + extra_field.append(UINT16_MAX - 4, 'a'); |
| 1095 | + |
| 1096 | + base::ScopedTempDir temp_dir; |
| 1097 | + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 1098 | + base::FilePath zip_file = temp_dir.GetPath().AppendASCII("extrafield.zip"); |
| 1099 | + |
| 1100 | + zipFile zf = zipOpen(zip_file.AsUTF8Unsafe().c_str(), APPEND_STATUS_CREATE); |
| 1101 | + ASSERT_NE(zf, nullptr); |
| 1102 | + |
| 1103 | + // Adding a member with 2^16 byte extra field should work. |
| 1104 | + EXPECT_EQ(zipOpenNewFileInZip(zf, "a", nullptr, extra_field.data(), |
| 1105 | + extra_field.size(), extra_field.data(), |
| 1106 | + extra_field.size(), nullptr, Z_DEFLATED, |
| 1107 | + Z_DEFAULT_COMPRESSION), |
| 1108 | + ZIP_OK); |
| 1109 | + EXPECT_EQ(zipWriteInFileInZip(zf, "1", 1), ZIP_OK); |
| 1110 | + EXPECT_EQ(zipCloseFileInZip(zf), ZIP_OK); |
| 1111 | + |
| 1112 | + // More then 2^16 bytes doesn't work. Neither for size_extrafield_local, nor |
| 1113 | + // size_extrafield_global. |
| 1114 | + std::string extra_field_long = extra_field + 'x'; |
| 1115 | + EXPECT_EQ( |
| 1116 | + zipOpenNewFileInZip(zf, "b", nullptr, nullptr, 0, extra_field_long.data(), |
| 1117 | + extra_field_long.size(), nullptr, Z_DEFLATED, |
| 1118 | + Z_DEFAULT_COMPRESSION), |
| 1119 | + ZIP_PARAMERROR); |
| 1120 | + EXPECT_EQ(zipOpenNewFileInZip(zf, "b", nullptr, extra_field_long.data(), |
| 1121 | + extra_field_long.size(), nullptr, 0, nullptr, |
| 1122 | + Z_DEFLATED, Z_DEFAULT_COMPRESSION), |
| 1123 | + ZIP_PARAMERROR); |
| 1124 | + |
| 1125 | + EXPECT_EQ(zipClose(zf, nullptr), ZIP_OK); |
| 1126 | + |
| 1127 | + // Check that the data can be read back. |
| 1128 | + unzFile uzf = unzOpen(zip_file.AsUTF8Unsafe().c_str()); |
| 1129 | + ASSERT_NE(uzf, nullptr); |
| 1130 | + char buf[UINT16_MAX + 1] = {0}; |
| 1131 | + |
| 1132 | + ASSERT_EQ(unzGoToFirstFile(uzf), UNZ_OK); |
| 1133 | + ASSERT_EQ(unzGetCurrentFileInfo(uzf, nullptr, nullptr, 0, buf, |
| 1134 | + sizeof(buf) - 1, nullptr, 0), |
| 1135 | + UNZ_OK); |
| 1136 | + EXPECT_EQ(std::string(buf), extra_field); |
| 1137 | + |
| 1138 | + EXPECT_EQ(unzGoToNextFile(uzf), UNZ_END_OF_LIST_OF_FILE); |
| 1139 | + EXPECT_EQ(unzClose(uzf), UNZ_OK); |
| 1140 | +} |
0 commit comments