From: Jonathan Wakely Date: Fri, 5 Jan 2018 22:47:42 +0000 (+0000) Subject: PR libstdc++/79283 fix filesystem::read_symlink for /proc X-Git-Tag: releases/gcc-6.5.0~607 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=df165a2e1bd9aabf326d85dedff885caf6930d5a;p=thirdparty%2Fgcc.git 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: r256294 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 63fcb50596f2..67e67763cd1c 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. + 2017-12-14 Jonathan Wakely PR libstdc++/59568 diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc index 0dcb1b410fc0..b242c04e1c38 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; }