From df7dd7127c4a0db0583668cefa72bc5f2c2e088c Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 5 Jan 2018 21:27:20 +0000 Subject: [PATCH] PR libstdc++/79283 fix filesystem::read_symlink for /proc Backport from mainline 2017-10-25 Jonathan Wakely PR libstdc++/79283 * src/filesystem/ops.cc (read_symlink): Handle st_size being zero. From-SVN: r256286 --- libstdc++-v3/ChangeLog | 8 +++++++ libstdc++-v3/src/filesystem/ops.cc | 37 ++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 68c56b10207..be33fd264c0 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2018-01-05 Jonathan Wakely + + Backport from mainline + 2017-10-25 Jonathan Wakely + + PR libstdc++/79283 + * src/filesystem/ops.cc (read_symlink): Handle st_size being zero. + 2018-01-04 Ville Voutilainen Backport from mainline diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc index c711de16f06..8c403263a4b 100644 --- a/libstdc++-v3/src/filesystem/ops.cc +++ b/libstdc++-v3/src/filesystem/ops.cc @@ -1199,26 +1199,45 @@ fs::read_symlink(const path& p) fs::path fs::read_symlink(const path& p, error_code& ec) { + path result; #ifdef _GLIBCXX_HAVE_SYS_STAT_H stat_type st; if (::lstat(p.c_str(), &st)) { ec.assign(errno, std::generic_category()); - return {}; + return result; } - std::string buf(st.st_size, '\0'); - ssize_t len = ::readlink(p.c_str(), &buf.front(), buf.size()); - if (len == -1) + std::string buf(st.st_size ? st.st_size + 1 : 128, '\0'); + do { - ec.assign(errno, std::generic_category()); - return {}; + ssize_t len = ::readlink(p.c_str(), &buf.front(), buf.size()); + if (len == -1) + { + ec.assign(errno, std::generic_category()); + return result; + } + else if (len == (ssize_t)buf.size()) + { + if (buf.size() > 4096) + { + ec.assign(ENAMETOOLONG, std::generic_category()); + return result; + } + buf.resize(buf.size() * 2); + } + else + { + buf.resize(len); + result.assign(buf); + ec.clear(); + break; + } } - ec.clear(); - return path{buf.data(), buf.data()+len}; + while (true); #else ec = std::make_error_code(std::errc::not_supported); - return {}; #endif + return result; }