summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2017-02-07 21:51:58 +0000
committerEric Fiselier <eric@efcs.ca>2017-02-07 21:51:58 +0000
commitfecf0579406081010195d87cd5a74608c33d5004 (patch)
tree05c53031ad924f49d37b333d86d4ee67eaa596ce /src
parent2b495bd9d72a3905b347ee0848c62ac80a23cbc9 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@294360 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'src')
-rw-r--r--src/experimental/filesystem/directory_iterator.cpp5
-rw-r--r--src/experimental/filesystem/path.cpp18
2 files changed, 16 insertions, 7 deletions
diff --git a/src/experimental/filesystem/directory_iterator.cpp b/src/experimental/filesystem/directory_iterator.cpp
index 8c9d05c2f..25135857d 100644
--- a/src/experimental/filesystem/directory_iterator.cpp
+++ b/src/experimental/filesystem/directory_iterator.cpp
@@ -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;
}
}
diff --git a/src/experimental/filesystem/path.cpp b/src/experimental/filesystem/path.cpp
index daf2c2bba..f49d4cd2d 100644
--- a/src/experimental/filesystem/path.cpp
+++ b/src/experimental/filesystem/path.cpp
@@ -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();
}