Simplify coding around path_contains_parent_reference().
Given the existing stipulation that path_contains_parent_reference() must only be invoked on canonicalized paths, we can simplify things in the wake of commit c10f830c5. It is now only possible to see ".." at the start of a relative path. That means we can simplify path_contains_parent_reference() itself quite a bit, and it makes the two existing outside call sites dead code, since they'd already checked that the path is absolute. We could now fold path_contains_parent_reference() into its only remaining caller path_is_relative_and_below_cwd(). But it seems better to leave it as a separately callable function, in case any extensions are using it. Also document the pre-existing requirement for path_is_relative_and_below_cwd's input to be likewise canonicalized. Shenhao Wang and Tom Lane Discussion: https://postgr.es/m/OSBPR01MB4214FA221FFE046F11F2AD74F2D49@OSBPR01MB4214.jpnprd01.prod.outlook.com
This commit is contained in:
parent
c10f830c51
commit
b426bd48ee
@ -88,12 +88,6 @@ convert_and_check_filename(text *arg)
|
||||
*/
|
||||
if (is_absolute_path(filename))
|
||||
{
|
||||
/* Disallow '/a/b/data/..' */
|
||||
if (path_contains_parent_reference(filename))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("reference to parent directory (\"..\") not allowed")));
|
||||
|
||||
/* Allow absolute paths if within DataDir */
|
||||
if (!path_is_prefix_of_path(DataDir, filename))
|
||||
ereport(ERROR,
|
||||
|
@ -72,12 +72,6 @@ convert_and_check_filename(text *arg)
|
||||
*/
|
||||
if (is_absolute_path(filename))
|
||||
{
|
||||
/* Disallow '/a/b/data/..' */
|
||||
if (path_contains_parent_reference(filename))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("reference to parent directory (\"..\") not allowed")));
|
||||
|
||||
/*
|
||||
* Allow absolute paths if within DataDir or Log_directory, even
|
||||
* though Log_directory might be outside DataDir.
|
||||
|
@ -494,27 +494,21 @@ canonicalize_path(char *path)
|
||||
* Detect whether a path contains any parent-directory references ("..")
|
||||
*
|
||||
* The input *must* have been put through canonicalize_path previously.
|
||||
*
|
||||
* This is a bit tricky because we mustn't be fooled by "..a.." (legal)
|
||||
* nor "C:.." (legal on Unix but not Windows).
|
||||
*/
|
||||
bool
|
||||
path_contains_parent_reference(const char *path)
|
||||
{
|
||||
int path_len;
|
||||
|
||||
/*
|
||||
* Once canonicalized, an absolute path cannot contain any ".." at all,
|
||||
* while a relative path could contain ".."(s) only at the start. So it
|
||||
* is sufficient to check the start of the path, after skipping any
|
||||
* Windows drive/network specifier.
|
||||
*/
|
||||
path = skip_drive(path); /* C: shouldn't affect our conclusion */
|
||||
|
||||
path_len = strlen(path);
|
||||
|
||||
/*
|
||||
* ".." could be the whole path; otherwise, if it's present it must be at
|
||||
* the beginning, in the middle, or at the end.
|
||||
*/
|
||||
if (strcmp(path, "..") == 0 ||
|
||||
strncmp(path, "../", 3) == 0 ||
|
||||
strstr(path, "/../") != NULL ||
|
||||
(path_len >= 3 && strcmp(path + path_len - 3, "/..") == 0))
|
||||
if (path[0] == '.' &&
|
||||
path[1] == '.' &&
|
||||
(path[2] == '\0' || path[2] == '/'))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -522,10 +516,11 @@ path_contains_parent_reference(const char *path)
|
||||
|
||||
/*
|
||||
* Detect whether a path is only in or below the current working directory.
|
||||
*
|
||||
* The input *must* have been put through canonicalize_path previously.
|
||||
*
|
||||
* An absolute path that matches the current working directory should
|
||||
* return false (we only want relative to the cwd). We don't allow
|
||||
* "/../" even if that would keep us under the cwd (it is too hard to
|
||||
* track that).
|
||||
* return false (we only want relative to the cwd).
|
||||
*/
|
||||
bool
|
||||
path_is_relative_and_below_cwd(const char *path)
|
||||
|
Loading…
x
Reference in New Issue
Block a user