mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-26 15:56:18 +02:00
Fix (highly unlikely) race condition in readLink
Used to determine symlink size with stat and value with readlink. This could technically result in garbage if symlink changed between calls. Also gets around the broken stat implementation in our network filesystem (returns size + 1 giving a byte of garbage).
This commit is contained in:
parent
12991152be
commit
07d2c6d213
1 changed files with 11 additions and 12 deletions
|
@ -216,18 +216,17 @@ bool pathExists(const Path & path)
|
||||||
Path readLink(const Path & path)
|
Path readLink(const Path & path)
|
||||||
{
|
{
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
struct stat st = lstat(path);
|
for (ssize_t bufSize = PATH_MAX/4; true; bufSize += bufSize/2) {
|
||||||
if (!S_ISLNK(st.st_mode))
|
|
||||||
throw Error(format("'%1%' is not a symlink") % path);
|
|
||||||
auto bufSize = std::max(st.st_size, (off_t) PATH_MAX + 1);
|
|
||||||
char buf[bufSize];
|
char buf[bufSize];
|
||||||
ssize_t rlsize = readlink(path.c_str(), buf, bufSize);
|
ssize_t rlSize = readlink(path.c_str(), buf, bufSize);
|
||||||
if (rlsize == -1)
|
if (rlSize == -1)
|
||||||
|
if (errno == EINVAL)
|
||||||
|
throw Error(format("'%1%' is not a symlink") % path);
|
||||||
|
else
|
||||||
throw SysError(format("reading symbolic link '%1%'") % path);
|
throw SysError(format("reading symbolic link '%1%'") % path);
|
||||||
else if (rlsize > bufSize)
|
else if (rlSize < bufSize)
|
||||||
throw Error(format("symbolic link '%1%' size overflow %2% > %3%")
|
return string(buf, rlSize);
|
||||||
% path % rlsize % bufSize);
|
}
|
||||||
return string(buf, rlsize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue