I wrote:
> I didn't much like the patch as-is; we should think a little harder
> about fixing the logic properly.
Like, say, this. (Very poorly tested but I think it's right.)
regards, tom lane
*** src/port/path.c.orig Thu Aug 11 21:39:22 2005
--- src/port/path.c Thu Aug 11 22:46:05 2005
***************
*** 226,231 ****
--- 226,232 ----
{
char *p, *to_p;
bool was_sep = false;
+ int pending_strips;
#ifdef WIN32
/*
***************
*** 277,296 ****
/*
* Remove any trailing uses of "." and process ".." ourselves
*/
for (;;)
{
int len = strlen(path);
if (len > 2 && strcmp(path + len - 2, "/.") == 0)
trim_directory(path);
! /* We can only deal with "/usr/local/..", not "/usr/local/../.." */
! else if (len > 3 && strcmp(path + len - 3, "/..") == 0 &&
! (len != 5 || strcmp(path, "../..") != 0) &&
! (len < 6 || strcmp(path + len - 6, "/../..") != 0))
{
trim_directory(path);
! trim_directory(path); /* remove directory above */
}
else
break;
--- 278,302 ----
/*
* Remove any trailing uses of "." and process ".." ourselves
+ *
+ * This is tricky because of the possibility of /foo/bar/baz/../..
*/
+ pending_strips = 0;
for (;;)
{
int len = strlen(path);
if (len > 2 && strcmp(path + len - 2, "/.") == 0)
trim_directory(path);
! else if (len > 3 && strcmp(path + len - 3, "/..") == 0)
{
trim_directory(path);
! pending_strips++; /* must remove directory above */
! }
! else if (pending_strips > 0)
! {
! trim_directory(path);
! pending_strips--;
}
else
break;