changeset 14541:e038fae3f7f0 draft

(svn r19112) -Fix [FS#3611]: don't crash on broken lng file
author smatz <smatz@openttd.org>
date Fri, 12 Feb 2010 23:39:44 +0000
parents b568841a8e39
children 7d2b798c1ad9
files src/strings.cpp
diffstat 1 files changed, 31 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -1239,15 +1239,16 @@
 
 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 @@
 	}
 
 #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);