On Thu, Jan 16, 2003 at 08:25:32PM -0600, Dave Dykstra wrote: > It doesn't look to me like your new code looks at the last > component of the path like the old one might have.
Right. I thought to myself as I was re-writing the function that that wouldn't be possible (to end with ".."), but I could be wrong. We might as well handle that possibility. > I don't expect that the strdups are of significant overhead, but as long > as you've gone through the trouble to rewrite it I suppose we might as > well use it (assuming you have handled the last component ok). Since it's so close to a release we might want to delay committing this until afterwards. However, it is a pretty simple change, so feel free to use it if you feel the risk is justified. I've attached a new version of the patch. ..wayne..
Index: util.c --- util.c 15 Jan 2003 17:49:44 -0000 1.118 +++ util.c 17 Jan 2003 06:29:25 -0000 @@ -793,49 +793,42 @@ * * @sa t_unsafe.c **/ -int unsafe_symlink(const char *dest_path, const char *src_path) +int unsafe_symlink(const char *dest, const char *src) { - char *tok, *src, *dest; + const char *name, *slash; int depth = 0; /* all absolute and null symlinks are unsafe */ - if (!dest_path || !*dest_path || *dest_path == '/') return 1; - - src = strdup(src_path); - 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_path); - 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); }