aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfuzzard <fuzzard@users.noreply.github.com>2022-09-27 08:08:43 +1000
committerGitHub <noreply@github.com>2022-09-27 08:08:43 +1000
commite34e70cf9b305ff17f8d4d6a6f3f0efbae80dd71 (patch)
tree9b5d554238fba89e5a8b18a7c972960cc1b20902
parent62300083e120758f844f0469f9ab5c201c84f490 (diff)
parent26aa5ee2dd86ee0ec5a70f178f17d766411b98a4 (diff)
Merge pull request #21840 from neo1973/ZipManager
Prevent unaligned memory accesses in CZipManager
-rw-r--r--xbmc/filesystem/ZipManager.cpp55
-rw-r--r--xbmc/filesystem/ZipManager.h11
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;