bool TransferManager::IsWithinParentDirectory()

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;
        }