in src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp [1290:1339]
bool TransferManager::IsWithinParentDirectory(Aws::String parentDirectory, Aws::String filePath)
{
char delimiter[] = { Aws::FileSystem::PATH_DELIM, 0 };
// normalize to unix ending style
Aws::Utils::StringUtils::Replace(parentDirectory, delimiter, "/");
Aws::Utils::StringUtils::Replace(filePath, delimiter, "/");
if(!parentDirectory.empty() && parentDirectory.back() == '/')
{
parentDirectory.resize(parentDirectory.size() - 1);
}
if (filePath.rfind(parentDirectory, 0) == 0) // if starts_with
{
filePath = filePath.substr(parentDirectory.size());
}
else
{
return false;
}
size_t level = 0;
for(size_t i = 0; i < filePath.size(); ++i)
{
if('/' == filePath[i])
{
while (i + 1 < filePath.size() && '/' == filePath[i+1]) // Skip all "//"
{
++i;
}
if(i + 2 < filePath.size() && '.' == filePath[i+1] && '/' == filePath[i+2]) // if "/./"
{
continue;
}
if(i + 2 < filePath.size() && '.' == filePath[i+1] && '.' == filePath[i+2]) // if "/.."
{
if(i + 3 == filePath.size() || (i + 3 < filePath.size() && '/' == filePath[i+3])) // if "/.." or "/../"
{
if(0 == level) {
return false; // attempting to escape parent
}
level--;
}
}
level++;
}
}
return true;
}