aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2017-11-01 17:09:14 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2017-11-01 17:09:14 +0000
commit50e248f0c8dd85a0e1778050d998f4010d87ed46 (patch)
tree16c56de4fe2646dcaa19c9f79c802bcde54acda5 /libstdc++-v3
parent37a2c475252b26895732fefbbb0050c864ba698d (diff)
downloadgcc-50e248f0c8dd85a0e1778050d998f4010d87ed46.zip
gcc-50e248f0c8dd85a0e1778050d998f4010d87ed46.tar.gz
gcc-50e248f0c8dd85a0e1778050d998f4010d87ed46.tar.bz2
PR libstdc++/82777 fix path normalization for dot-dot
PR libstdc++/82777 * src/filesystem/std-path.cc (path::lexically_normal): Remove dot-dot elements correctly. * testsuite/27_io/filesystem/path/generation/normal.cc: Add testcase. * testsuite/util/testsuite_fs.h (compare_paths): Improve exception text. From-SVN: r254317
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog9
-rw-r--r--libstdc++-v3/src/filesystem/std-path.cc33
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc4
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_fs.h2
4 files changed, 43 insertions, 5 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index b5adbb1..9805e4b 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,12 @@
+2017-11-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/82777
+ * src/filesystem/std-path.cc (path::lexically_normal): Remove dot-dot
+ elements correctly.
+ * testsuite/27_io/filesystem/path/generation/normal.cc: Add testcase.
+ * testsuite/util/testsuite_fs.h (compare_paths): Improve exception
+ text.
+
2017-10-30 Jonathan Wakely <jwakely@redhat.com>
* include/Makefile.am (stamp-bits-sup): Do not create broken symlink
diff --git a/libstdc++-v3/src/filesystem/std-path.cc b/libstdc++-v3/src/filesystem/std-path.cc
index 1e2a8fa..330aee7 100644
--- a/libstdc++-v3/src/filesystem/std-path.cc
+++ b/libstdc++-v3/src/filesystem/std-path.cc
@@ -388,10 +388,35 @@ path::lexically_normal() const
#endif
if (is_dotdot(p))
{
- if (ret.has_filename() && !is_dotdot(ret.filename()))
- ret.remove_filename();
- else if (ret.has_filename() || !ret.has_root_directory())
- ret /= p;
+ if (ret.has_filename())
+ {
+ // remove a non-dot-dot filename immediately followed by /..
+ if (!is_dotdot(ret.filename()))
+ ret.remove_filename();
+ else
+ ret /= p;
+ }
+ else if (!ret.has_relative_path())
+ {
+ if (!ret.is_absolute())
+ ret /= p;
+ }
+ else
+ {
+ // Got a path with a relative path (i.e. at least one non-root
+ // element) and no filename at the end (i.e. empty last element),
+ // so must have a trailing slash. See what is before it.
+ auto elem = std::prev(ret.end(), 2);
+ if (elem->has_filename() && !is_dotdot(*elem))
+ {
+ // Remove the filename before the trailing slash
+ // (equiv. to ret = ret.parent_path().remove_filename())
+ ret._M_pathname.erase(elem._M_cur->_M_pos);
+ ret._M_cmpts.erase(elem._M_cur, ret._M_cmpts.end());
+ }
+ else // ???
+ ret /= p;
+ }
}
else if (is_dot(p))
ret /= path();
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc
index 789ce18..df3b715 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc
@@ -46,6 +46,10 @@ test02()
compare_paths( path().lexically_normal(), "" );
compare_paths( path("/..").lexically_normal(), "/" );
+
+ // PR libstdc++/82777
+ compare_paths( path("./a/b/c/../.././b/c").lexically_normal(), "a/b/c" );
+ compare_paths( path("/a/b/c/../.././b/c").lexically_normal(), "/a/b/c" );
}
void
diff --git a/libstdc++-v3/testsuite/util/testsuite_fs.h b/libstdc++-v3/testsuite/util/testsuite_fs.h
index 47f5609..c18dae2 100644
--- a/libstdc++-v3/testsuite/util/testsuite_fs.h
+++ b/libstdc++-v3/testsuite/util/testsuite_fs.h
@@ -40,7 +40,7 @@ namespace __gnu_test
{
#define PATH_CHK(p1, p2, fn) \
if ( p1.fn() != p2.fn() ) \
- throw test_fs::filesystem_error( #fn, p1, p2, \
+ throw test_fs::filesystem_error("comparing '" #fn "' failed", p1, p2, \
std::make_error_code(std::errc::invalid_argument) )
void