aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bpkg/manifest14
-rw-r--r--bpkg/manifest.cxx30
-rw-r--r--tests/repository-location/driver.cxx7
3 files changed, 38 insertions, 13 deletions
diff --git a/bpkg/manifest b/bpkg/manifest
index 0c7c693..cc45bb4 100644
--- a/bpkg/manifest
+++ b/bpkg/manifest
@@ -392,18 +392,18 @@ namespace bpkg
bool
absolute () const
{
- return local () && path_.absolute ();
+ if (empty ())
+ throw std::logic_error ("empty location");
+
+ // Note that in remote locations path is always relative.
+ //
+ return path_.absolute ();
}
bool
relative () const
{
- if (empty ())
- throw std::logic_error ("empty location");
-
- // Note that in remote locations path is always absolute.
- //
- return path_.relative ();
+ return local () && path_.relative ();
}
const butl::dir_path&
diff --git a/bpkg/manifest.cxx b/bpkg/manifest.cxx
index 771cfaa..d421e7e 100644
--- a/bpkg/manifest.cxx
+++ b/bpkg/manifest.cxx
@@ -945,11 +945,15 @@ namespace bpkg
//
auto p (l.find ('/', 7));
- // Chop the path part. Note that we translate empty path to "/".
+ // The remote repository location with no path specified is not a valid
+ // one. Keep the path_ member empty so the later check for emptiness
+ // will throw invalid_argument exception.
//
- path_ = p != string::npos
- ? dir_path (l, p, string::npos)
- : dir_path ("/");
+ if (p != string::npos)
+ // Chop the path part. Path is saved as a relative one to be of the
+ // same type on different operating systems including Windows.
+ //
+ path_ = dir_path (l, p + 1, string::npos);
// Put the lower-cased version of the host part into host_.
// Chances are good it will stay unmodified.
@@ -1093,6 +1097,22 @@ namespace bpkg
throw invalid_argument ("invalid path");
}
+ // Need to check path for emptiness before proceeding further as a valid
+ // non empty location can not have an empty path_ member. Note that path
+ // can become empty as a result of normalize () call. Example of such a
+ // path is 'a/..'.
+ //
+ if (path_.empty ())
+ throw invalid_argument ("empty path");
+
+ // Need to check that URL path do not go past the root directory of a WEB
+ // server. We can not rely on the above normalize() function call doing
+ // this check as soon as path_ member contains a relative directory for the
+ // remote location.
+ //
+ if (remote () && *path_.begin () == "..")
+ throw invalid_argument ("invalid path");
+
// Finish calculating the canonical name, unless we are relative.
//
if (relative ())
@@ -1152,7 +1172,7 @@ namespace bpkg
if (port_ != 0)
p += ":" + to_string (port_);
- return p + path_.posix_string ();
+ return p + "/" + path_.posix_string ();
}
// repository_manifest
diff --git a/tests/repository-location/driver.cxx b/tests/repository-location/driver.cxx
index db7c0e2..4ee0c57 100644
--- a/tests/repository-location/driver.cxx
+++ b/tests/repository-location/driver.cxx
@@ -54,7 +54,6 @@ main (int argc, char* argv[])
{
// Test invalid locations.
//
-
// Invalid host.
//
assert (bad_location ("http:///aa/bb"));
@@ -95,11 +94,17 @@ main (int argc, char* argv[])
assert (bad_location ("1"));
assert (bad_location ("1/"));
+ assert (bad_location ("1/.."));
assert (bad_location ("bbb"));
assert (bad_location ("aaa/bbb"));
assert (bad_location ("/aaa/bbb"));
+ assert (bad_location ("http://aa"));
+ assert (bad_location ("http://aa/"));
+ assert (bad_location ("http://aa/b/.."));
+ assert (bad_location ("http://aa/."));
assert (bad_location ("http://aa/bb"));
assert (bad_location ("http://a.com/../c/1/aa"));
+ assert (bad_location ("http://a.com/a/b/../../../c/1/aa"));
// Invalid version.
//