system/core
Révision | 4d4f8b30b850a3e15638c28aabef7b0f3aedeb8c (tree) |
---|---|
l'heure | 2018-01-04 17:45:08 |
Auteur | Chih-Wei Huang <cwhuang@linu...> |
Commiter | Chih-Wei Huang |
Merge tag 'android-7.1.2_r36' into nougat-x86
Android 7.1.2 Release 36 (N2G48H)
@@ -18,6 +18,7 @@ | ||
18 | 18 | #include <utils/Unicode.h> |
19 | 19 | |
20 | 20 | #include <stddef.h> |
21 | +#include <limits.h> | |
21 | 22 | |
22 | 23 | #if defined(_WIN32) |
23 | 24 | # undef nhtol |
@@ -178,7 +179,15 @@ ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len) | ||
178 | 179 | size_t ret = 0; |
179 | 180 | const char32_t *end = src + src_len; |
180 | 181 | while (src < end) { |
181 | - ret += utf32_codepoint_utf8_length(*src++); | |
182 | + size_t char_len = utf32_codepoint_utf8_length(*src++); | |
183 | + if (SSIZE_MAX - char_len < ret) { | |
184 | + // If this happens, we would overflow the ssize_t type when | |
185 | + // returning from this function, so we cannot express how | |
186 | + // long this string is in an ssize_t. | |
187 | + android_errorWriteLog(0x534e4554, "37723026"); | |
188 | + return -1; | |
189 | + } | |
190 | + ret += char_len; | |
182 | 191 | } |
183 | 192 | return ret; |
184 | 193 | } |
@@ -438,14 +447,23 @@ ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len) | ||
438 | 447 | size_t ret = 0; |
439 | 448 | const char16_t* const end = src + src_len; |
440 | 449 | while (src < end) { |
450 | + size_t char_len; | |
441 | 451 | if ((*src & 0xFC00) == 0xD800 && (src + 1) < end |
442 | 452 | && (*(src + 1) & 0xFC00) == 0xDC00) { |
443 | 453 | // surrogate pairs are always 4 bytes. |
444 | - ret += 4; | |
454 | + char_len = 4; | |
445 | 455 | src += 2; |
446 | 456 | } else { |
447 | - ret += utf32_codepoint_utf8_length((char32_t) *src++); | |
457 | + char_len = utf32_codepoint_utf8_length((char32_t)*src++); | |
458 | + } | |
459 | + if (SSIZE_MAX - char_len < ret) { | |
460 | + // If this happens, we would overflow the ssize_t type when | |
461 | + // returning from this function, so we cannot express how | |
462 | + // long this string is in an ssize_t. | |
463 | + android_errorWriteLog(0x534e4554, "37723026"); | |
464 | + return -1; | |
448 | 465 | } |
466 | + ret += char_len; | |
449 | 467 | } |
450 | 468 | return ret; |
451 | 469 | } |
@@ -358,6 +358,8 @@ static int32_t MapCentralDirectory(int fd, const char* debug_file_name, | ||
358 | 358 | return result; |
359 | 359 | } |
360 | 360 | |
361 | +static inline bool ReadAtOffset(int fd, uint8_t* buf, size_t len, off64_t off); | |
362 | + | |
361 | 363 | /* |
362 | 364 | * Parses the Zip archive's Central Directory. Allocates and populates the |
363 | 365 | * hash table. |
@@ -436,6 +438,22 @@ static int32_t ParseZipArchive(ZipArchive* archive) { | ||
436 | 438 | return -1; |
437 | 439 | } |
438 | 440 | } |
441 | + | |
442 | + uint32_t lfh_start_bytes; | |
443 | + if (!ReadAtOffset(archive->fd, reinterpret_cast<uint8_t*>(&lfh_start_bytes), | |
444 | + sizeof(uint32_t), 0)) { | |
445 | + ALOGW("Zip: Unable to read header for entry at offset == 0."); | |
446 | + return -1; | |
447 | + } | |
448 | + | |
449 | + if (lfh_start_bytes != LocalFileHeader::kSignature) { | |
450 | + ALOGW("Zip: Entry at offset zero has invalid LFH signature %" PRIx32, lfh_start_bytes); | |
451 | +#if defined(__ANDROID__) | |
452 | + android_errorWriteLog(0x534e4554, "64211847"); | |
453 | +#endif | |
454 | + return -1; | |
455 | + } | |
456 | + | |
439 | 457 | ALOGV("+++ zip good scan %" PRIu16 " entries", num_entries); |
440 | 458 | |
441 | 459 | return 0; |
@@ -603,6 +603,55 @@ TEST(ziparchive, StreamUncompressedBadCrc) { | ||
603 | 603 | CloseArchive(handle); |
604 | 604 | } |
605 | 605 | |
606 | +// A zip file whose local file header at offset zero is corrupted. | |
607 | +// | |
608 | +// --------------- | |
609 | +// cat foo > a.txt | |
610 | +// zip a.zip a.txt | |
611 | +// cat a.zip | xxd -i | |
612 | +// | |
613 | +// Manual changes : | |
614 | +// [2] = 0xff // Corrupt the LFH signature of entry 0. | |
615 | +// [3] = 0xff // Corrupt the LFH signature of entry 0. | |
616 | +static const std::vector<uint8_t> kZipFileWithBrokenLfhSignature{ | |
617 | + //[lfh-sig-----------], [lfh contents--------------------------------- | |
618 | + 0x50, 0x4b, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x80, | |
619 | + //-------------------------------------------------------------------- | |
620 | + 0x09, 0x4b, 0xa8, 0x65, 0x32, 0x7e, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, | |
621 | + //-------------------------------] [file-name-----------------], [--- | |
622 | + 0x00, 0x00, 0x05, 0x00, 0x1c, 0x00, 0x61, 0x2e, 0x74, 0x78, 0x74, 0x55, | |
623 | + // entry-contents------------------------------------------------------ | |
624 | + 0x54, 0x09, 0x00, 0x03, 0x51, 0x24, 0x8b, 0x59, 0x51, 0x24, 0x8b, 0x59, | |
625 | + //-------------------------------------------------------------------- | |
626 | + 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0x89, 0x42, 0x00, 0x00, 0x04, 0x88, | |
627 | + //-------------------------------------], [cd-record-sig-------], [--- | |
628 | + 0x13, 0x00, 0x00, 0x66, 0x6f, 0x6f, 0x0a, 0x50, 0x4b, 0x01, 0x02, 0x1e, | |
629 | + // cd-record----------------------------------------------------------- | |
630 | + 0x03, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x80, 0x09, 0x4b, 0xa8, | |
631 | + //-------------------------------------------------------------------- | |
632 | + 0x65, 0x32, 0x7e, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, | |
633 | + //-------------------------------------------------------------------- | |
634 | + 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa0, | |
635 | + //-] [lfh-file-header-off-], [file-name-----------------], [extra---- | |
636 | + 0x81, 0x00, 0x00, 0x00, 0x00, 0x61, 0x2e, 0x74, 0x78, 0x74, 0x55, 0x54, | |
637 | + //-------------------------------------------------------------------- | |
638 | + 0x05, 0x00, 0x03, 0x51, 0x24, 0x8b, 0x59, 0x75, 0x78, 0x0b, 0x00, 0x01, | |
639 | + //-------------------------------------------------------], [eocd-sig- | |
640 | + 0x04, 0x89, 0x42, 0x00, 0x00, 0x04, 0x88, 0x13, 0x00, 0x00, 0x50, 0x4b, | |
641 | + //-------], [--------------------------------------------------------- | |
642 | + 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x4b, 0x00, | |
643 | + //-------------------------------------------] | |
644 | + 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
645 | + | |
646 | +TEST(ziparchive, BrokenLfhSignature) { | |
647 | + TemporaryFile tmp_file; | |
648 | + ASSERT_NE(-1, tmp_file.fd); | |
649 | + ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, &kZipFileWithBrokenLfhSignature[0], | |
650 | + kZipFileWithBrokenLfhSignature.size())); | |
651 | + ZipArchiveHandle handle; | |
652 | + ASSERT_EQ(-1, OpenArchiveFd(tmp_file.fd, "LeadingNonZipBytes", &handle)); | |
653 | +} | |
654 | + | |
606 | 655 | int main(int argc, char** argv) { |
607 | 656 | ::testing::InitGoogleTest(&argc, argv); |
608 | 657 |