X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/32f761755e2cfee243a1513c9ea9871586463fa6..d542c20c5fd636c6973b7bcbed6be2bedbed4bcd:/util.c diff --git a/util.c b/util.c index 63af7dab..e5638f05 100644 --- a/util.c +++ b/util.c @@ -793,49 +793,42 @@ int u_strcmp(const char *cs1, const char *cs2) * * @sa t_unsafe.c **/ -int unsafe_symlink(char *dest, char *src) +int unsafe_symlink(const char *dest, const char *src) { - char *tok; + const char *name, *slash; int depth = 0; /* all absolute and null symlinks are unsafe */ - if (!dest || !(*dest) || (*dest == '/')) return 1; - - src = strdup(src); - if (!src) out_of_memory("unsafe_symlink"); + if (!dest || !*dest || *dest == '/') return 1; /* find out what our safety margin is */ - for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) { - if (strcmp(tok,"..") == 0) { + for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) { + if (strncmp(name, "../", 3) == 0) { depth=0; - } else if (strcmp(tok,".") == 0) { + } else if (strncmp(name, "./", 2) == 0) { /* nothing */ } else { depth++; } } - free(src); - - /* drop by one to account for the filename portion */ - depth--; - - dest = strdup(dest); - if (!dest) out_of_memory("unsafe_symlink"); + if (strcmp(name, "..") == 0) + depth = 0; - for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) { - if (strcmp(tok,"..") == 0) { - depth--; - } else if (strcmp(tok,".") == 0) { + for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) { + if (strncmp(name, "../", 3) == 0) { + /* if at any point we go outside the current directory + then stop - it is unsafe */ + if (--depth < 0) + return 1; + } else if (strncmp(name, "./", 2) == 0) { /* nothing */ } else { depth++; } - /* if at any point we go outside the current directory then - stop - it is unsafe */ - if (depth < 0) break; } + if (strcmp(name, "..") == 0) + depth--; - free(dest); return (depth < 0); }