diff options
author | smatz <smatz@openttd.org> | 2010-02-12 23:39:44 +0000 |
---|---|---|
committer | smatz <smatz@openttd.org> | 2010-02-12 23:39:44 +0000 |
commit | 66837b1edd9d9bac0f77487db12c08d584b4e86b (patch) | |
tree | 00dc9262b89df0cca8279b495538fb3543f026d3 | |
parent | 171dbb78311806507e22b92dd5a675447507d2f6 (diff) | |
download | openttd-66837b1edd9d9bac0f77487db12c08d584b4e86b.tar.xz |
(svn r19112) -Fix [FS#3611]: don't crash on broken lng file
-rw-r--r-- | src/strings.cpp | 48 |
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); |