Fix bugs in filesystem detected by _LIBCPP_ASSERT.

Recently I turned on libc++'s debug mode assertions when
CMake is configured with -DLIBCXX_ENABLE_ASSERTIONS=ON. This
change exposed assertion failures caused by bugs in filesystem.
This patch fixes those failures.

The first bug was that `PathParser` was using front()/back()
on empty string views in order to get the address of the character.
However this is UB on empty strings. Those operations now use data()
to obtain the pointer.

The second bug was that directory_iterator attempted to capture errno when it
was unset and there was an assertion to detect this.

llvm-svn: 294360
This commit is contained in:
Eric Fiselier 2017-02-07 21:51:58 +00:00
parent a2c2d94dcb
commit c0d5590a3b
2 changed files with 16 additions and 7 deletions

View File

@ -45,11 +45,12 @@ inline bool set_or_throw(std::error_code& my_ec,
inline path::string_type posix_readdir(DIR *dir_stream, error_code& ec) {
struct dirent* dir_entry_ptr = nullptr;
errno = 0; // zero errno in order to detect errors
ec.clear();
if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) {
ec = capture_errno();
if (errno)
ec = capture_errno();
return {};
} else {
ec.clear();
return dir_entry_ptr->d_name;
}
}

View File

@ -56,13 +56,13 @@ public:
}
PosPtr peek() const noexcept {
auto End = &Path.back() + 1;
auto TkEnd = getNextTokenStartPos();
auto End = getAfterBack();
return TkEnd == End ? nullptr : TkEnd;
}
void increment() noexcept {
const PosPtr End = &Path.back() + 1;
const PosPtr End = getAfterBack();
const PosPtr Start = getNextTokenStartPos();
if (Start == End)
return makeState(PS_AtEnd);
@ -109,7 +109,7 @@ public:
}
void decrement() noexcept {
const PosPtr REnd = &Path.front() - 1;
const PosPtr REnd = getBeforeFront();
const PosPtr RStart = getCurrentTokenStartPos() - 1;
switch (State) {
@ -195,19 +195,27 @@ private:
RawEntry = {};
}
PosPtr getAfterBack() const noexcept {
return Path.data() + Path.size();
}
PosPtr getBeforeFront() const noexcept {
return Path.data() - 1;
}
/// \brief Return a pointer to the first character after the currently
/// lexed element.
PosPtr getNextTokenStartPos() const noexcept {
switch (State) {
case PS_BeforeBegin:
return &Path.front();
return Path.data();
case PS_InRootName:
case PS_InRootDir:
case PS_InFilenames:
return &RawEntry.back() + 1;
case PS_InTrailingSep:
case PS_AtEnd:
return &Path.back() + 1;
return getAfterBack();
}
_LIBCPP_UNREACHABLE();
}