diff options
author | fuzzard <fuzzard@users.noreply.github.com> | 2022-09-27 08:08:43 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-27 08:08:43 +1000 |
commit | e34e70cf9b305ff17f8d4d6a6f3f0efbae80dd71 (patch) | |
tree | 9b5d554238fba89e5a8b18a7c972960cc1b20902 | |
parent | 62300083e120758f844f0469f9ab5c201c84f490 (diff) | |
parent | 26aa5ee2dd86ee0ec5a70f178f17d766411b98a4 (diff) |
Merge pull request #21840 from neo1973/ZipManager
Prevent unaligned memory accesses in CZipManager
-rw-r--r-- | xbmc/filesystem/ZipManager.cpp | 55 | ||||
-rw-r--r-- | xbmc/filesystem/ZipManager.h | 11 |
2 files changed, 36 insertions, 30 deletions
diff --git a/xbmc/filesystem/ZipManager.cpp b/xbmc/filesystem/ZipManager.cpp index ce1e542b35..710cfbc53d 100644 --- a/xbmc/filesystem/ZipManager.cpp +++ b/xbmc/filesystem/ZipManager.cpp @@ -110,8 +110,7 @@ bool CZipManager::GetZipList(const CURL& url, std::vector<SZipEntry>& items) return false; for (int i=blockSize-1; !found && (i >= 0); i--) { - if (Endian_SwapLE32(*(reinterpret_cast<unsigned int*>(buffer.data() + i))) == - ZIP_END_CENTRAL_HEADER) + if (Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer.data() + i)) == ZIP_END_CENTRAL_HEADER) { // Set current position to start of end of central directory mFile.Seek(fileSize-ECDREC_SIZE+1-(blockSize*nb)+i,SEEK_SET); @@ -128,8 +127,7 @@ bool CZipManager::GetZipList(const CURL& url, std::vector<SZipEntry>& items) return false; for (int i=extraBlockSize-1; !found && (i >= 0); i--) { - if (Endian_SwapLE32(*(reinterpret_cast<unsigned int*>(buffer.data() + i))) == - ZIP_END_CENTRAL_HEADER) + if (Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer.data() + i)) == ZIP_END_CENTRAL_HEADER) { // Set current position to start of end of central directory mFile.Seek(fileSize-ECDREC_SIZE+1-searchSize+i,SEEK_SET); @@ -274,38 +272,37 @@ bool CZipManager::ExtractArchive(const CURL& archive, const std::string& strPath // Read local file header void CZipManager::readHeader(const char* buffer, SZipEntry& info) { - info.header = Endian_SwapLE32(*(const unsigned int*)buffer); - info.version = Endian_SwapLE16(*(const unsigned short*)(buffer+4)); - info.flags = Endian_SwapLE16(*(const unsigned short*)(buffer+6)); - info.method = Endian_SwapLE16(*(const unsigned short*)(buffer+8)); - info.mod_time = Endian_SwapLE16(*(const unsigned short*)(buffer+10)); - info.mod_date = Endian_SwapLE16(*(const unsigned short*)(buffer+12)); - info.crc32 = Endian_SwapLE32(*(const unsigned int*)(buffer+14)); - info.csize = Endian_SwapLE32(*(const unsigned int*)(buffer+18)); - info.usize = Endian_SwapLE32(*(const unsigned int*)(buffer+22)); - info.flength = Endian_SwapLE16(*(const unsigned short*)(buffer+26)); - info.elength = Endian_SwapLE16(*(const unsigned short*)(buffer+28)); + info.header = Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer)); + info.version = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 4)); + info.flags = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 6)); + info.method = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 8)); + info.mod_time = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 10)); + info.mod_date = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 12)); + info.crc32 = Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer + 14)); + info.csize = Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer + 18)); + info.usize = Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer + 22)); + info.flength = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 26)); + info.elength = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 28)); } // Read central file header (from central directory) void CZipManager::readCHeader(const char* buffer, SZipEntry& info) { - info.header = Endian_SwapLE32(*(const unsigned int*)buffer); + info.header = Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer)); // Skip version made by - info.version = Endian_SwapLE16(*(const unsigned short*)(buffer+6)); - info.flags = Endian_SwapLE16(*(const unsigned short*)(buffer+8)); - info.method = Endian_SwapLE16(*(const unsigned short*)(buffer+10)); - info.mod_time = Endian_SwapLE16(*(const unsigned short*)(buffer+12)); - info.mod_date = Endian_SwapLE16(*(const unsigned short*)(buffer+14)); - info.crc32 = Endian_SwapLE32(*(const unsigned int*)(buffer+16)); - info.csize = Endian_SwapLE32(*(const unsigned int*)(buffer+20)); - info.usize = Endian_SwapLE32(*(const unsigned int*)(buffer+24)); - info.flength = Endian_SwapLE16(*(const unsigned short*)(buffer+28)); - info.eclength = Endian_SwapLE16(*(const unsigned short*)(buffer+30)); - info.clength = Endian_SwapLE16(*(const unsigned short*)(buffer+32)); + info.version = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 6)); + info.flags = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 8)); + info.method = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 10)); + info.mod_time = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 12)); + info.mod_date = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 14)); + info.crc32 = Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer + 16)); + info.csize = Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer + 20)); + info.usize = Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer + 24)); + info.flength = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 28)); + info.eclength = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 30)); + info.clength = Endian_SwapLE16(ReadUnaligned<uint16_t>(buffer + 32)); // Skip disk number start, internal/external file attributes - info.lhdrOffset = Endian_SwapLE32(*(const unsigned int*)(buffer+42)); - + info.lhdrOffset = Endian_SwapLE32(ReadUnaligned<uint32_t>(buffer + 42)); } void CZipManager::release(const std::string& strPath) diff --git a/xbmc/filesystem/ZipManager.h b/xbmc/filesystem/ZipManager.h index 45754152eb..3fba27f481 100644 --- a/xbmc/filesystem/ZipManager.h +++ b/xbmc/filesystem/ZipManager.h @@ -19,9 +19,10 @@ #define CHDR_SIZE 46 #define ECDREC_SIZE 22 +#include <cstring> +#include <map> #include <string> #include <vector> -#include <map> class CURL; @@ -67,6 +68,14 @@ public: private: std::map<std::string,std::vector<SZipEntry> > mZipMap; std::map<std::string,int64_t> mZipDate; + + template<typename T> + static T ReadUnaligned(const void* mem) + { + T var; + std::memcpy(&var, mem, sizeof(T)); + return var; + } }; extern CZipManager g_ZipManager; |