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(); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits