Re: Bug in canonicalize_path()

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
Cc: William ZHANG <uniware(at)zedware(dot)org>, pgsql-patches(at)postgresql(dot)org
Subject: Re: Bug in canonicalize_path()
Date: 2005-08-12 21:14:49
Message-ID: 23841.1123881289@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-patches

Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us> writes:
> In my first attempt, I counted the number of ".." groups, then went up
> to remove each "..", and them remove a regular directory for each "..".
> And then you have this case:

> /usr/local/../bin/../..

> Here you hit the first ".." as you are going up. It just seemed like a
> lost cause.

BTW, you were right: this is a *lot* harder than it looks at first
glance. Here's what I ended up with:

/*
* Remove any trailing uses of "." and process ".." ourselves
*
* Note that "/../.." should reduce to just "/", while "../.." has to
* be kept as-is. In the latter case we put back mistakenly trimmed
* ".." components below. Also note that we want a Windows drive spec
* to be visible to trim_directory(), but it's not part of the logic
* that's looking at the name components; hence distinction between
* path and spath.
*/
spath = skip_drive(path);
pending_strips = 0;
for (;;)
{
int len = strlen(spath);

if (len >= 2 && strcmp(spath + len - 2, "/.") == 0)
trim_directory(path);
else if (strcmp(spath, ".") == 0)
{
/* Want to leave "." alone, but "./.." has to become ".." */
if (pending_strips > 0)
*spath = '\0';
break;
}
else if ((len >= 3 && strcmp(spath + len - 3, "/..") == 0) ||
strcmp(spath, "..") == 0)
{
trim_directory(path);
pending_strips++;
}
else if (pending_strips > 0 && *spath != '\0')
{
/* trim a regular directory name cancelled by ".." */
trim_directory(path);
pending_strips--;
/* foo/.. should become ".", not empty */
if (*spath == '\0')
strcpy(spath, ".");
}
else
break;
}

if (pending_strips > 0)
{
/*
* We could only get here if path is now totally empty (other than
* a possible drive specifier on Windows).
* We have to put back one or more ".."'s that we took off.
*/
while (--pending_strips > 0)
strcat(path, "../");
strcat(path, "..");
}
}

regards, tom lane

In response to

Browse pgsql-patches by date

  From Date Subject
Next Message Bruce Momjian 2005-08-12 21:20:39 Re: [HACKERS] Duplicate object names in GRANT
Previous Message Bruce Momjian 2005-08-12 21:12:30 Re: Bitmap index AM