[libcxx] r294360 - Fix bugs in filesystem detected by _LIBCPP_ASSERT.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 7 13:51:58 PST 2017


Author: ericwf
Date: Tue Feb  7 15:51:58 2017
New Revision: 294360

URL: http://llvm.org/viewvc/llvm-project?rev=294360&view=rev
Log:
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.

Modified:
    libcxx/trunk/src/experimental/filesystem/directory_iterator.cpp
    libcxx/trunk/src/experimental/filesystem/path.cpp

Modified: libcxx/trunk/src/experimental/filesystem/directory_iterator.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/experimental/filesystem/directory_iterator.cpp?rev=294360&r1=294359&r2=294360&view=diff
==============================================================================
--- libcxx/trunk/src/experimental/filesystem/directory_iterator.cpp (original)
+++ libcxx/trunk/src/experimental/filesystem/directory_iterator.cpp Tue Feb  7 15:51:58 2017
@@ -45,11 +45,12 @@ inline bool set_or_throw(std::error_code
 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;
     }
 }

Modified: libcxx/trunk/src/experimental/filesystem/path.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/experimental/filesystem/path.cpp?rev=294360&r1=294359&r2=294360&view=diff
==============================================================================
--- libcxx/trunk/src/experimental/filesystem/path.cpp (original)
+++ libcxx/trunk/src/experimental/filesystem/path.cpp Tue Feb  7 15:51:58 2017
@@ -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();
   }




More information about the cfe-commits mailing list