Skip to content
Permalink
Browse files

Fix undefined behaviour in iso-fs

Cannot reinterpret cast bytes to ints due to potential alignment problems.
  • Loading branch information...
TheCycoONE committed May 4, 2019
1 parent 99e3285 commit 0a8a0503a4f88da89ee8e35719a7f8c87b704e0f
Showing with 41 additions and 36 deletions.
  1. +4 −12 CorsixTH/Src/iso_fs.cpp
  2. +36 −0 CorsixTH/Src/th.h
  3. +1 −24 CorsixTH/Src/th_sound.cpp
@@ -22,6 +22,7 @@ SOFTWARE.

#include "iso_fs.h"
#include "th_lua_internal.h"
#include "th.h"
#include <cstring>
#include <cstdarg>
#include <cstdlib>
@@ -80,15 +81,6 @@ constexpr const char* vblk_0_filename = "VBLK-0.TAB";
/// size is 2048.
constexpr size_t min_sector_size = 2048;

template <class T> inline T read_native_int(const uint8_t *p)
{
// ISO 9660 commonly encodes multi-byte integers as little endian followed
// by big endian. Note that the first byte of iEndianness will be a zero on
// little endian systems, and a one on big endian.
static const uint16_t iEndianness = 0x0100;
return reinterpret_cast<const T*>(p)[*reinterpret_cast<const uint8_t*>(&iEndianness)];
}

void trim_identifier_version(const uint8_t* sIdent, uint8_t& iLength)
{
for(uint8_t i = 0; i < iLength; ++i)
@@ -135,8 +127,8 @@ class iso_file_entry {
public:
iso_file_entry()=default;
iso_file_entry(const uint8_t* b) {
data_sector = read_native_int<uint32_t>(b + file_sector_offset);
data_length = read_native_int<uint32_t>(b + file_data_length_offset);
data_sector = bytes_to_uint32_le(b + file_sector_offset);
data_length = bytes_to_uint32_le(b + file_data_length_offset);
flags = b[file_flags_offset];
uint8_t filename_length = b[filename_length_offset];
trim_identifier_version(b + filename_offset, filename_length);
@@ -332,7 +324,7 @@ bool iso_filesystem::initialise(std::FILE* fRawFile)
{
if(aBuffer[0] == vdt_privary_volume)
{
sector_size = read_native_int<uint16_t>(aBuffer + 128);
sector_size = bytes_to_uint16_le(aBuffer + 128);
find_hosp_directory(aBuffer + 156, 34, 0);
if(files.empty())
{
@@ -92,4 +92,40 @@ class th_string_list
std::vector<uint8_t> string_buffer;
};

/**
* Convert 4 bytes representing uint32 in little endian representation into a
* uint32.
*
* @param bytes A pointer to the first of 4 sequential bytes in memory making
* up the uint32.
*/
inline uint32_t bytes_to_uint32_le(const uint8_t* bytes)
{
uint32_t res = bytes[3];
res <<= 8;
res |= bytes[2];
res <<= 8;
res |= bytes[1];
res <<= 8;
res |= bytes[0];

return res;
}

/**
* Convert 2 bytes representing uint16 in little endian representation into a
* uint16.
*
* @param bytes A pointer to the first of 2 sequential bytes in memory making
* up the uint16.
*/
inline uint16_t bytes_to_uint16_le(const uint8_t* bytes)
{
uint16_t res = bytes[1];
res <<= 8;
res |= bytes[0];

return res;
}

#endif // CORSIX_TH_TH_H_
@@ -22,6 +22,7 @@ SOFTWARE.

#include "config.h"
#include "th_sound.h"
#include "th.h"
#include <cmath>
#include <new>
#include <cstring>
@@ -37,30 +38,6 @@ sound_archive::~sound_archive()
delete[] data;
}

namespace {

/**
* Convert 4 bytes representing uint32 in little endian representation into a
* uint32.
*
* @param bytes A pointer to the first of 4 sequential bytes in memory making
* up the uint32.
*/
uint32_t bytes_to_uint32_le(const uint8_t* bytes)
{
uint32_t res = bytes[3];
res <<= 8;
res |= bytes[2];
res <<= 8;
res |= bytes[1];
res <<= 8;
res |= bytes[0];

return res;
}

} // namespace

bool sound_archive::load_from_th_file(const uint8_t* pData, size_t iDataLength)
{
if(iDataLength < sizeof(uint32_t) + sizeof(sound_dat_file_header))

0 comments on commit 0a8a050

Please sign in to comment.
You can’t perform that action at this time.