summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2014-04-25 21:29:54 +0000
committerrubidium <rubidium@openttd.org>2014-04-25 21:29:54 +0000
commit5ef2042819ea612a50b6ba01411cc9b083e34096 (patch)
tree122f71354001aff8dbda4d047d4f9ec06f2492cc
parent08eeec15bed443e5c6c0e6cd58f44c604b7aca09 (diff)
downloadopenttd-5ef2042819ea612a50b6ba01411cc9b083e34096.tar.xz
(svn r26514) -Fix: rewrite link-in-tar handling so it doesn't use strncpy and it doesn't overrun its buffers anymore
-rw-r--r--src/fileio.cpp51
-rw-r--r--src/safeguards.h2
2 files changed, 31 insertions, 22 deletions
diff --git a/src/fileio.cpp b/src/fileio.cpp
index 4ef4f1f93..a72950bc7 100644
--- a/src/fileio.cpp
+++ b/src/fileio.cpp
@@ -851,29 +851,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);
-
- /* 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;
+ char *next = strchr(pos, PATHSEPCHAR);
+ if (next == NULL) {
+ next = pos + strlen(pos);
+ } else {
+ /* Terminate the substring up to the path separator character. */
+ *next++= '\0';
+ }
+
+ 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/safeguards.h b/src/safeguards.h
index d2b388721..12d704879 100644
--- a/src/safeguards.h
+++ b/src/safeguards.h
@@ -36,7 +36,7 @@
/* Use strecpy instead. */
#define strcpy SAFEGUARD_DO_NOT_USE_THIS_METHOD
-//#define strncpy SAFEGUARD_DO_NOT_USE_THIS_METHOD
+#define strncpy SAFEGUARD_DO_NOT_USE_THIS_METHOD
/* Use strecat instead. */
#define strcat SAFEGUARD_DO_NOT_USE_THIS_METHOD