From b720a16a1c59c83860f3092b90a4d87c5f507901 Mon Sep 17 00:00:00 2001 From: frosch Date: Tue, 29 Apr 2014 18:35:01 +0000 Subject: [PATCH] (svn r26543) [1.4] -Backport from trunk: - Fix: Buffer overruns in handling of symbolic links inside tars (r26514) - Fix: Incorrect usage of strecpy (r26505, r26485) - Fix: Reading console input on dedicated server relied on unspecified behaviour (r26496) --- src/fileio.cpp | 49 +++++++++++++++++++++++---------------- src/game/game_text.cpp | 2 +- src/strgen/strgen.cpp | 2 +- src/video/dedicated_v.cpp | 7 +++--- 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index f88d8deeaf..c9d30051e2 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -849,29 +849,38 @@ bool TarScanner::AddFile(const char *filename, size_t basepath_length, const cha char *pos = link; while (*pos != '\0') { - char *next = strchr(link, PATHSEPCHAR); - if (next == NULL) next = pos + strlen(pos); + char *next = strchr(pos, PATHSEPCHAR); + if (next == NULL) { + next = pos + strlen(pos); + } else { + /* Terminate the substring up to the path separator character. */ + *next++= '\0'; + } - /* Skip '.' (current dir) */ - if (next != pos + 1 || pos[0] != '.') { - if (next == pos + 2 && pos[0] == '.' && pos[1] == '.') { - /* level up */ - if (dest[0] == '\0') { - DEBUG(misc, 1, "Ignoring link pointing outside of data directory: %s -> %s", name, link); - break; - } - - /* Truncate 'dest' after last PATHSEPCHAR. - * This assumes that the truncated part is a real directory and not a link. */ - destpos = strrchr(dest, PATHSEPCHAR); - if (destpos == NULL) destpos = dest; - } else { - /* Append at end of 'dest' */ - if (destpos != dest) *(destpos++) = PATHSEPCHAR; - strncpy(destpos, pos, next - pos); // Safe as we do '\0'-termination ourselves - destpos += next - pos; + if (strcmp(pos, ".") == 0) { + /* Skip '.' (current dir) */ + } else if (strcmp(pos, "..") == 0) { + /* level up */ + if (dest[0] == '\0') { + DEBUG(misc, 1, "Ignoring link pointing outside of data directory: %s -> %s", name, link); + break; } + + /* Truncate 'dest' after last PATHSEPCHAR. + * This assumes that the truncated part is a real directory and not a link. */ + destpos = strrchr(dest, PATHSEPCHAR); + if (destpos == NULL) destpos = dest; *destpos = '\0'; + } else { + /* Append at end of 'dest' */ + if (destpos != dest) destpos = strecpy(destpos, PATHSEP, lastof(dest)); + destpos = strecpy(destpos, pos, lastof(dest)); + } + + if (destpos >= lastof(dest)) { + DEBUG(misc, 0, "The length of a link in tar-file '%s' is too large (malformed?)", filename); + fclose(f); + return false; } pos = next; diff --git a/src/game/game_text.cpp b/src/game/game_text.cpp index cd9721b8ab..6fe008753a 100644 --- a/src/game/game_text.cpp +++ b/src/game/game_text.cpp @@ -377,7 +377,7 @@ void ReconsiderGameScriptLanguage() if (_current_data == NULL) return; char temp[MAX_PATH]; - strecpy(temp, _current_language->file, temp + sizeof(temp)); + strecpy(temp, _current_language->file, lastof(temp)); /* Remove the extension */ char *l = strrchr(temp, '.'); diff --git a/src/strgen/strgen.cpp b/src/strgen/strgen.cpp index 5d04538413..c407f23454 100644 --- a/src/strgen/strgen.cpp +++ b/src/strgen/strgen.cpp @@ -561,7 +561,7 @@ int CDECL main(int argc, char *argv[]) /* rename the .txt (input-extension) to .lng */ r = strrchr(pathbuf, '.'); if (r == NULL || strcmp(r, ".txt") != 0) r = strchr(pathbuf, '\0'); - ttd_strlcpy(r, ".lng", (size_t)(r - pathbuf)); + strecpy(r, ".lng", lastof(pathbuf)); LanguageFileWriter writer(pathbuf); writer.WriteLang(data); diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index 8e5b9ea91c..ed02fc76ef 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -99,6 +99,9 @@ static void WINAPI CheckForConsoleInput() HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); for (;;) { ReadFile(hStdin, _win_console_thread_buffer, lengthof(_win_console_thread_buffer), &nb, NULL); + if (nb >= lengthof(_win_console_thread_buffer)) nb = lengthof(_win_console_thread_buffer) - 1; + _win_console_thread_buffer[nb] = '\0'; + /* Signal input waiting that input is read and wait for it being handled * SignalObjectAndWait() should be used here, but it's unsupported in Win98< */ SetEvent(_hInputReady); @@ -243,9 +246,7 @@ static void DedicatedHandleKeyInput() SetEvent(_hWaitForInputHandling); #endif - /* strtok() does not 'forget' \r\n if the string starts with it, - * so we have to manually remove that! */ - strtok(input_line, "\r\n"); + /* Remove trailing \r or \n */ for (char *c = input_line; *c != '\0'; c++) { if (*c == '\n' || *c == '\r' || c == lastof(input_line)) { *c = '\0';