From 5ef2042819ea612a50b6ba01411cc9b083e34096 Mon Sep 17 00:00:00 2001 From: rubidium Date: Fri, 25 Apr 2014 21:29:54 +0000 Subject: (svn r26514) -Fix: rewrite link-in-tar handling so it doesn't use strncpy and it doesn't overrun its buffers anymore --- src/fileio.cpp | 51 ++++++++++++++++++++++++++++++--------------------- src/safeguards.h | 2 +- 2 files changed, 31 insertions(+), 22 deletions(-) (limited to 'src') 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 -- cgit v1.2.3-54-g00ecf