Limit number of symlinks that canonical() will resolve
* src/filesystem/ops.cc (canonical): Simplify error handling and limit number of symlinks that can be resolved. From-SVN: r228043
This commit is contained in:
parent
429ee11aa3
commit
07dc170b6f
@ -1,3 +1,8 @@
|
||||
2015-09-23 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* src/filesystem/ops.cc (canonical): Simplify error handling and
|
||||
limit number of symlinks that can be resolved.
|
||||
|
||||
2015-09-23 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Remove _GLIBCXX_
|
||||
|
@ -116,6 +116,7 @@ fs::canonical(const path& p, const path& base, error_code& ec)
|
||||
{
|
||||
const path pa = absolute(p, base);
|
||||
path result;
|
||||
|
||||
#ifdef _GLIBCXX_USE_REALPATH
|
||||
char_ptr buf{ nullptr };
|
||||
# if _XOPEN_VERSION < 700
|
||||
@ -137,18 +138,9 @@ fs::canonical(const path& p, const path& base, error_code& ec)
|
||||
}
|
||||
#endif
|
||||
|
||||
auto fail = [&ec, &result](int e) mutable {
|
||||
if (!ec.value())
|
||||
ec.assign(e, std::generic_category());
|
||||
result.clear();
|
||||
};
|
||||
|
||||
if (!exists(pa, ec))
|
||||
{
|
||||
fail(ENOENT);
|
||||
return result;
|
||||
}
|
||||
// else we can assume no unresolvable symlink loops
|
||||
return result;
|
||||
// else: we know there are (currently) no unresolvable symlink loops
|
||||
|
||||
result = pa.root_path();
|
||||
|
||||
@ -156,20 +148,19 @@ fs::canonical(const path& p, const path& base, error_code& ec)
|
||||
for (auto& f : pa.relative_path())
|
||||
cmpts.push_back(f);
|
||||
|
||||
while (!cmpts.empty())
|
||||
int max_allowed_symlinks = 40;
|
||||
|
||||
while (!cmpts.empty() && !ec)
|
||||
{
|
||||
path f = std::move(cmpts.front());
|
||||
cmpts.pop_front();
|
||||
|
||||
if (f.compare(".") == 0)
|
||||
if (is_dot(f))
|
||||
{
|
||||
if (!is_directory(result, ec))
|
||||
{
|
||||
fail(ENOTDIR);
|
||||
break;
|
||||
}
|
||||
if (!is_directory(result, ec) && !ec)
|
||||
ec.assign(ENOTDIR, std::generic_category());
|
||||
}
|
||||
else if (f.compare("..") == 0)
|
||||
else if (is_dotdot(f))
|
||||
{
|
||||
auto parent = result.parent_path();
|
||||
if (parent.empty())
|
||||
@ -184,27 +175,30 @@ fs::canonical(const path& p, const path& base, error_code& ec)
|
||||
if (is_symlink(result, ec))
|
||||
{
|
||||
path link = read_symlink(result, ec);
|
||||
if (!ec.value())
|
||||
if (!ec)
|
||||
{
|
||||
if (link.is_absolute())
|
||||
{
|
||||
result = link.root_path();
|
||||
link = link.relative_path();
|
||||
}
|
||||
if (--max_allowed_symlinks == 0)
|
||||
ec.assign(ELOOP, std::generic_category());
|
||||
else
|
||||
result.remove_filename();
|
||||
{
|
||||
if (link.is_absolute())
|
||||
{
|
||||
result = link.root_path();
|
||||
link = link.relative_path();
|
||||
}
|
||||
else
|
||||
result.remove_filename();
|
||||
|
||||
cmpts.insert(cmpts.begin(), link.begin(), link.end());
|
||||
cmpts.insert(cmpts.begin(), link.begin(), link.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ec.value() || !exists(result, ec))
|
||||
{
|
||||
fail(ENOENT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ec || !exists(result, ec))
|
||||
result.clear();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user