diff options
-rw-r--r-- | bpkg/manifest | 14 | ||||
-rw-r--r-- | bpkg/manifest.cxx | 30 | ||||
-rw-r--r-- | tests/repository-location/driver.cxx | 7 |
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. // |