Проверьте, находится ли std :: filesystem :: path внутри каталога - PullRequest
2 голосов
/ 09 апреля 2020

У меня есть root путь, представленный std::filesystem::path. Я хочу добавить предоставленное пользователем имя файла к этому пути и убедиться, что полученный путь не находится в каталоге root.

Например:

    std::filesystem::path root = "/foo/bar";
    std::filesystem::path userFile = "ham/spam";
    std::filesystem::path finalPath = root / userFile;

Окончательный путь в порядке , это внутри /foo/bar. Но если я передам ../ham/spam переменной userFile, это приведет к тому, что файл будет находиться за пределами определения rootPath.

Как проверить, что полученный файл находится в допустимых границах?

1 Ответ

4 голосов
/ 09 апреля 2020

Во-первых, вам нужно нормализовать окончательный путь . Это удалит все . и .. s в пути. Затем вам нужно проверить, есть ли какие-либо несоответствия в диапазоне итераторов каталога относительно root. И для этого есть стандартный библиотечный алгоритм .

Итак, в целом код выглядит так:

std::optional<fs::path> MakeAbsolute(const fs::path &root, const fs::path &userPath)
{
    auto finalPath = (root / userPath).lexically_normal();

    auto[rootEnd, nothing] = std::mismatch(root.begin(), root.end(), finalPath.begin());

    if(rootEnd != root.end())
        return std::nullopt;

    return finalPath;
}

Обратите внимание, что это работает только теоретически; пользователь мог использовать shenlink shenanigans в каталоге root, чтобы выйти из каталога root. Вам нужно будет использовать canonical вместо lexically_normal, чтобы этого не произошло. Однако canonical требует , чтобы существовал путь, поэтому, если это путь к файлу / каталогу, который необходимо создать, он не будет работать.

...