summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsmatz <smatz@openttd.org>2010-02-12 23:39:44 +0000
committersmatz <smatz@openttd.org>2010-02-12 23:39:44 +0000
commit66837b1edd9d9bac0f77487db12c08d584b4e86b (patch)
tree00dc9262b89df0cca8279b495538fb3543f026d3
parent171dbb78311806507e22b92dd5a675447507d2f6 (diff)
downloadopenttd-66837b1edd9d9bac0f77487db12c08d584b4e86b.tar.xz
(svn r19112) -Fix [FS#3611]: don't crash on broken lng file
-rw-r--r--src/strings.cpp48
1 files changed, 31 insertions, 17 deletions
diff --git a/src/strings.cpp b/src/strings.cpp
index 010106601..47bf3d2e2 100644
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -1239,15 +1239,16 @@ static inline void SortNetworkLanguages() {}
bool ReadLanguagePack(int lang_index)
{
- int tot_count, i;
+ /* Current language pack */
size_t len;
- char **langpack_offs;
- char *s;
+ LanguagePack *lang_pack = (LanguagePack *)ReadFileToMem(_dynlang.ent[lang_index].file, &len, 200000);
+ if (lang_pack == NULL) return false;
- LanguagePack *lang_pack = (LanguagePack*)ReadFileToMem(_dynlang.ent[lang_index].file, &len, 200000);
+ /* End of read data (+ terminating zero added in ReadFileToMem()) */
+ const char *end = (char *)lang_pack + len + 1;
- if (lang_pack == NULL) return false;
- if (len < sizeof(LanguagePack) ||
+ /* We need at least one byte of lang_pack->data */
+ if (end <= lang_pack->data ||
lang_pack->ident != TO_LE32(LANGUAGE_PACK_IDENT) ||
lang_pack->version != TO_LE32(LANGUAGE_PACK_VERSION)) {
free(lang_pack);
@@ -1255,30 +1256,43 @@ bool ReadLanguagePack(int lang_index)
}
#if TTD_ENDIAN == TTD_BIG_ENDIAN
- for (i = 0; i != 32; i++) {
+ for (uint i = 0; i < 32; i++) {
lang_pack->offsets[i] = ReadLE16Aligned(&lang_pack->offsets[i]);
}
#endif /* TTD_ENDIAN == TTD_BIG_ENDIAN */
- tot_count = 0;
- for (i = 0; i != 32; i++) {
+ uint count = 0;
+ for (uint i = 0; i < 32; i++) {
uint num = lang_pack->offsets[i];
- _langtab_start[i] = tot_count;
+ _langtab_start[i] = count;
_langtab_num[i] = num;
- tot_count += num;
+ count += num;
}
/* Allocate offsets */
- langpack_offs = MallocT<char*>(tot_count);
+ char **langpack_offs = MallocT<char *>(count);
/* Fill offsets */
- s = lang_pack->data;
- for (i = 0; i != tot_count; i++) {
- len = (byte)*s;
- *s++ = '\0'; // zero terminate the string before.
- if (len >= 0xC0) len = ((len & 0x3F) << 8) + (byte)*s++;
+ char *s = lang_pack->data;
+ len = (byte)*s++;
+ for (uint i = 0; i < count; i++) {
+ if (s + len >= end) {
+ free(lang_pack);
+ free(langpack_offs);
+ return false;
+ }
+ if (len >= 0xC0) {
+ len = ((len & 0x3F) << 8) + (byte)*s++;
+ if (s + len >= end) {
+ free(lang_pack);
+ free(langpack_offs);
+ return false;
+ }
+ }
langpack_offs[i] = s;
s += len;
+ len = (byte)*s;
+ *s++ = '\0'; // zero terminate the string
}
free(_langpack);