Changeset - r11272:411ffa5b815a
[Not reviewed]
master
0 8 0
rubidium - 15 years ago 2009-03-06 01:23:25
rubidium@openttd.org
(svn r15626) -Fix [FS#2698]: UTF8 string handling could cause buffer overruns.
8 files changed with 37 insertions and 12 deletions:
0 comments (0 inline, 0 general)
src/console.cpp
Show inline comments
 
@@ -97,7 +97,7 @@ void IConsolePrint(ConsoleColour colour_
 
	 * characters and (when applicable) assign it to the console buffer */
 
	str = strdup(string);
 
	str_strip_colours(str);
 
	str_validate(str);
 
	str_validate(str, str + strlen(str));
 

	
 
	if (_network_dedicated) {
 
		fprintf(stdout, "%s\n", str);
src/fios.cpp
Show inline comments
 
@@ -247,7 +247,7 @@ bool FiosFileScanner::AddFile(const char
 
		t = (t == NULL) ? filename : (t + 1);
 
	}
 
	strecpy(fios->title, t, lastof(fios->title));
 
	str_validate(fios->title);
 
	str_validate(fios->title, lastof(fios->title));
 

	
 
	return true;
 
}
 
@@ -292,7 +292,7 @@ static void FiosGetFileList(SaveLoadDial
 
				fios->mtime = 0;
 
				strecpy(fios->name, d_name, lastof(fios->name));
 
				snprintf(fios->title, lengthof(fios->title), "%s" PATHSEP " (Directory)", d_name);
 
				str_validate(fios->title);
 
				str_validate(fios->title, lastof(fios->title));
 
			}
 
		}
 
		closedir(dir);
 
@@ -344,6 +344,7 @@ static void GetFileTitle(const char *fil
 
	size_t read = fread(title, 1, last - title, f);
 
	assert(title + read <= last);
 
	title[read] = '\0';
 
	str_validate(title, last);
 
	FioFCloseFile(f);
 
}
 

	
src/network/core/packet.cpp
Show inline comments
 
@@ -237,6 +237,7 @@ void Packet::Recv_string(char *buffer, s
 
{
 
	PacketSize pos;
 
	char *bufp = buffer;
 
	const char *last = buffer + size - 1;
 

	
 
	/* Don't allow reading from a closed socket */
 
	if (cs->HasClientQuit()) return;
 
@@ -253,7 +254,7 @@ void Packet::Recv_string(char *buffer, s
 
	}
 
	this->pos = pos;
 

	
 
	str_validate(bufp, allow_newlines);
 
	str_validate(bufp, last, allow_newlines);
 
}
 

	
 
#endif /* ENABLE_NETWORK */
src/saveload/oldloader.cpp
Show inline comments
 
@@ -232,6 +232,7 @@ static inline bool CheckOldSavegameType(
 

	
 
	bool ret = VerifyOldNameChecksum(temp, len);
 
	temp[len - 2] = '\0'; // name is nul-terminated in savegame, but it's better to be sure
 
	str_validate(temp, last);
 

	
 
	return ret;
 
}
src/saveload/saveload.cpp
Show inline comments
 
@@ -33,6 +33,7 @@
 
#include "../statusbar_gui.h"
 
#include "../fileio_func.h"
 
#include "../gamelog.h"
 
#include "../string_func.h"
 

	
 
#include "table/strings.h"
 

	
 
@@ -631,6 +632,7 @@ static void SlString(void *ptr, size_t l
 
		}
 

	
 
		((char*)ptr)[len] = '\0'; // properly terminate the string
 
		str_validate((char*)ptr, (char*)ptr + len);
 
	}
 
}
 

	
src/string.cpp
Show inline comments
 
@@ -97,13 +97,27 @@ char *CDECL str_fmt(const char *str, ...
 
}
 

	
 

	
 
void str_validate(char *str, bool allow_newlines, bool ignore)
 
void str_validate(char *str, const char *last, bool allow_newlines, bool ignore)
 
{
 
	/* Assume the ABSOLUTE WORST to be in str as it comes from the outside. */
 

	
 
	char *dst = str;
 
	WChar c;
 
	size_t len;
 
	while (*str != '\0') {
 
		size_t len = Utf8EncodedCharLen(*str);
 
		/* If the character is unknown, i.e. encoded length is 0
 
		 * we assume worst case for the length check.
 
		 * The length check is needed to prevent Utf8Decode to read
 
		 * over the terminating '\0' if that happens to be placed
 
		 * within the encoding of an UTF8 character. */
 
		if ((len == 0 && str + 4 > last) || str + len > last) break;
 

	
 
	for (len = Utf8Decode(&c, str); c != '\0'; len = Utf8Decode(&c, str)) {
 
		WChar c;
 
		len = Utf8Decode(&c, str);
 
		/* It's possible to encode the string termination character
 
		 * into a multiple bytes. This prevents those termination
 
		 * characters to be skipped */
 
		if (c == '\0') break;
 

	
 
		if (IsPrintable(c) && (c < SCC_SPRITE_START || c > SCC_SPRITE_END)) {
 
			/* Copy the character back. Even if dst is current the same as str
 
			 * (i.e. no characters have been changed) this is quicker than
src/string_func.h
Show inline comments
 
@@ -93,9 +93,15 @@ int CDECL seprintf(char *str, const char
 

	
 
char *CDECL str_fmt(const char *str, ...);
 

	
 
/** Scans the string for valid characters and if it finds invalid ones,
 
 * replaces them with a question mark '?' */
 
void str_validate(char *str, bool allow_newlines = false, bool ignore = false);
 
/**
 
 * Scans the string for valid characters and if it finds invalid ones,
 
 * replaces them with a question mark '?' (if not ignored)
 
 * @param str the string to validate
 
 * @param last the last valid character of str
 
 * @param allow_newlines whether newlines should be allowed or ignored
 
 * @param ignore whether to ignore or replace with a question mark
 
 */
 
void str_validate(char *str, const char *last, bool allow_newlines = false, bool ignore = false);
 

	
 
/** Scans the string for colour codes and strips them */
 
void str_strip_colours(char *str);
src/video/dedicated_v.cpp
Show inline comments
 
@@ -235,7 +235,7 @@ static void DedicatedHandleKeyInput()
 
			break;
 
		}
 
	}
 
	str_validate(input_line);
 
	str_validate(input_line, lastof(input_line));
 

	
 
	IConsoleCmdExec(input_line); // execute command
 
}
0 comments (0 inline, 0 general)