前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Windows VC++路径标准化-PathCchCanonicalize

Windows VC++路径标准化-PathCchCanonicalize

作者头像
ccf19881030
发布2022-09-21 10:36:33
8310
发布2022-09-21 10:36:33
举报
文章被收录于专栏:ccf19881030的博客ccf19881030的博客

外部输入的参数不能直接作为文件路径,防止被恶意攻击,比如构造一个跨目录限制的文件路径…/…/…/etc/passwd或…/…/boot.ini,或构造一个指向系统关键文件的链接文件symlink(“/etc/shadow”,“tmp/log”)。PS "./“表示当前目录,可以不写,”…/"表示当前目录的上一级目录,即当前目录的父目录。windows可以用PathCanonicalizeA或者PathCanonicalizeW检查文件目录是否标准,但是微软msdn官网不建议使用PathCanonicalize这个函数,如下图所示:

PathCanonicalizeA 函数
PathCanonicalizeA 函数

微软msdn官网说误用PathCanonicalizeA 会导致buffer溢出,建议使用更安全的PathCchCanonicalize或PathCchCanonicalizeEx 代替。

PathCchCanonicalize
PathCchCanonicalize

对PathCchCanonicalize函数的使用示例如下:

代码语言:javascript
复制
#include <Windows.h>
#include <pathcch.h>
#include <string>
#include <iostream>
#pragma comment(lib,"Pathcch.lib")

using namespace std;

//将string转换成wstring  
wstring String2WString(string str)
{
    wstring result;
    //获取缓冲区大小,并申请空间,缓冲区大小按字符计算  
    int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
    TCHAR* buffer = new TCHAR[len + 1];
    //多字节编码转换成宽字节编码  
    MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);
    buffer[len] = '\0';             //添加字符串结尾  
    //删除缓冲区并返回值  
    result.append(buffer);
    delete[] buffer;
    return result;
}

//将wstring转换成string  
string WString2String(wstring wstr)
{
    string result;
    //获取缓冲区大小,并申请空间,缓冲区大小事按字节计算的  
    int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
    char* buffer = new char[len + 1];
    //宽字节编码转换成多字节编码  
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), buffer, len, NULL, NULL);
    buffer[len] = '\0';
    //删除缓冲区并返回值  
    result.append(buffer);
    delete[] buffer;
    return result;
}

bool GetCanonicalizePath(const std::wstring& path, std::wstring& cannoPath)
{
    wchar_t tempArrPath[MAX_PATH] = { 0 };
    if (path.empty() || path.length() > MAX_PATH ||
        PathCchCanonicalize(tempArrPath, MAX_PATH, path.c_str()) != S_OK) {
        return false;
    }
    std::wstring resultPath = tempArrPath;
    cannoPath = resultPath;
    return true;
}

bool GetCanonicalizePathA(const std::string& path, std::string& cannoPath)
{
    std::wstring wstrPath = String2WString(path);
    wchar_t tempArrPath[MAX_PATH] = { 0 };
    if (wstrPath.empty() || wstrPath.length() > MAX_PATH ||
        PathCchCanonicalize(tempArrPath, MAX_PATH, wstrPath.c_str()) != S_OK) {
        return false;
    }
    std::wstring resultPath = tempArrPath;
    std::string strTempResultPath = WString2String(resultPath);
    cannoPath = strTempResultPath;
    return true;
}

int main(int argc, char* argv[])
{
    std::string fileFullPath = "D:\\name_1\\.\\name_2\\.\\name_3\\..\\name_4\\..";
    std::string canonicalizePath;
    bool bCanonicalizeOk = GetCanonicalizePathA(fileFullPath, canonicalizePath);
    if (bCanonicalizeOk) {
        std::cout << "canonicalizePath=" << canonicalizePath.c_str() << endl;  //  D:\name_1\name_2
    } else {
        std::cout << "GetCanonicalizePathA failed, lastErrorCode: " << GetLastError() << endl;
    };

    std::wstring fileFullWstrPath = L"D:\\name_1\\.\\name_2\\.\\name_3\\..\\name_4\\..";
    std::wstring canonicalizeWstrPath;
    bCanonicalizeOk = GetCanonicalizePath(fileFullWstrPath, canonicalizeWstrPath);
    if (bCanonicalizeOk) {
        std::cout << "canonicalizeWstrPath=" << WString2String(canonicalizeWstrPath).c_str() << endl;  //  D:\name_1\name_2
    } else {
        std::cout << "GetCanonicalizePathA failed, lastErrorCode: " << GetLastError() << endl;
    };

    return 0;
}

运行结果如下图所示:

运行测试结果
运行测试结果
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档