Title
path::lexically_relative causes surprising results if a filename can also be a root-name
Status
c++20
Section
[fs.path.gen]
Submitter
Billy O'Neal III

Created on 2018-02-23.00:00:00 last changed 45 months ago

Messages

Date: 2019-07-22.17:12:46

Proposed resolution:

This wording is relative to N4727.

  1. Change [fs.path.gen] as indicated:

    path lexically_relative(const path& base) const;
    

    -3- […]

    -4- Effects: If root_name() != base.root_name() is true or is_absolute() != base.is_absolute() is true or !has_root_directory() && base.has_root_directory() is true or if any filename in relative_path() or base.relative_path() can be interpreted as a root-name, returns path(). [Note: On a POSIX implementation, no filename in a relative-path is acceptable as a root-nameend note] Determines the first mismatched element of *this and base as if by:

    auto [a, b] = mismatch(begin(), end(), base.begin(), base.end());
    

    Then,

    1. (4.1) — if a == end() and b == base.end(), returns path("."); otherwise

    2. (4.2) — let n be the number of filename elements in [b, base.end()) that are not dot or dot-dot minus the number that are dot-dot. If n < 0, returns path(); otherwise

    3. (4.3) — returns an object of class path that is default-constructed, followed by

      1. (4.3.1) — application of operator/=(path("..")) n times, and then

      2. (4.3.2) — application of operator/= for each element in [a, end()).

Date: 2019-07-22.17:12:46

[ 2019 Cologne Wednesday night ]

Status to Ready

Date: 2019-01-20.00:00:00

[ 2019-01-20 Reflector prioritization ]

Set Priority to 2

Date: 2018-02-23.00:00:00

path::lexically_relative constructs the resulting path with operator/=. If any of the filename elements from *this are themselves acceptable root-names, operator/= will destroy any previous value, and take that root_name(). For example:

path("/a:/b:").lexically_relative("/a:/c:")

On a POSIX implementation, this would return path("../b:"), but on a Windows implementation, the "b:" element is interpreted as a root-name, and clobbers the entire result path, giving path("b:"). We should detect this problematic condition and fail (by returning path()).

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2019-11-19 14:48:30adminsetstatus: voting -> wp
2019-10-07 02:48:00adminsetstatus: ready -> voting
2019-07-22 17:12:46adminsetmessages: + msg10487
2019-07-22 17:12:46adminsetstatus: new -> ready
2019-01-20 16:20:00adminsetmessages: + msg10286
2018-03-03 17:00:07adminsetmessages: + msg9698
2018-02-23 00:00:00admincreate