summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormilek7 <me@milek7.pl>2021-03-28 00:12:32 +0100
committerMichael Lutz <michi@icosahedron.de>2021-04-02 10:12:25 +0200
commit295f34a9dfea9b141a3aefaee582cd6386779f29 (patch)
treec1e6442fd9213e253e84082cecc5967e0b7427b1
parentdd798d688b7e9ea6c7d4d01aea976dde5ec75f60 (diff)
downloadopenttd-295f34a9dfea9b141a3aefaee582cd6386779f29.tar.xz
Fix: Freeing LanguagePack with wrong size.
-rw-r--r--src/fileio.cpp7
-rw-r--r--src/fileio_func.h2
-rw-r--r--src/strings.cpp12
3 files changed, 13 insertions, 8 deletions
diff --git a/src/fileio.cpp b/src/fileio.cpp
index 9a9e7e05d..6b33f8aa2 100644
--- a/src/fileio.cpp
+++ b/src/fileio.cpp
@@ -1259,7 +1259,7 @@ void SanitizeFilename(char *filename)
* @return Pointer to new memory containing the loaded data, or \c nullptr if loading failed.
* @note If \a maxsize less than the length of the file, loading fails.
*/
-std::unique_ptr<char> ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize)
+std::unique_ptr<char[]> ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize)
{
FILE *in = fopen(filename.c_str(), "rb");
if (in == nullptr) return nullptr;
@@ -1271,10 +1271,7 @@ std::unique_ptr<char> ReadFileToMem(const std::string &filename, size_t &lenp, s
fseek(in, 0, SEEK_SET);
if (len > maxsize) return nullptr;
- /* std::unique_ptr assumes new/delete unless a custom deleter is supplied.
- * As we don't want to have to carry that deleter all over the place, use
- * new directly to allocate the memory instead of malloc. */
- std::unique_ptr<char> mem(static_cast<char *>(::operator new(len + 1)));
+ std::unique_ptr<char[]> mem = std::make_unique<char[]>(len + 1);
mem.get()[len] = 0;
if (fread(mem.get(), len, 1, in) != 1) return nullptr;
diff --git a/src/fileio_func.h b/src/fileio_func.h
index f373188fa..6dbaea897 100644
--- a/src/fileio_func.h
+++ b/src/fileio_func.h
@@ -49,7 +49,7 @@ const char *FiosGetScreenshotDir();
void SanitizeFilename(char *filename);
void AppendPathSeparator(std::string &buf);
void DeterminePaths(const char *exe);
-std::unique_ptr<char> ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize);
+std::unique_ptr<char[]> ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize);
bool FileExists(const std::string &filename);
bool ExtractTar(const std::string &tar_filename, Subdirectory subdir);
diff --git a/src/strings.cpp b/src/strings.cpp
index 02ca30f23..08e826141 100644
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -185,8 +185,16 @@ struct LanguagePack : public LanguagePackHeader {
char data[]; // list of strings
};
+struct LanguagePackDeleter {
+ void operator()(LanguagePack *langpack)
+ {
+ /* LanguagePack is in fact reinterpreted char[], we need to reinterpret it back to free it properly. */
+ delete[] reinterpret_cast<char*>(langpack);
+ }
+};
+
struct LoadedLanguagePack {
- std::unique_ptr<LanguagePack> langpack;
+ std::unique_ptr<LanguagePack, LanguagePackDeleter> langpack;
std::vector<char *> offsets;
@@ -1713,7 +1721,7 @@ bool ReadLanguagePack(const LanguageMetadata *lang)
{
/* Current language pack */
size_t len = 0;
- std::unique_ptr<LanguagePack> lang_pack(reinterpret_cast<LanguagePack *>(ReadFileToMem(lang->file, len, 1U << 20).release()));
+ std::unique_ptr<LanguagePack, LanguagePackDeleter> lang_pack(reinterpret_cast<LanguagePack *>(ReadFileToMem(lang->file, len, 1U << 20).release()));
if (!lang_pack) return false;
/* End of read data (+ terminating zero added in ReadFileToMem()) */