C++中一个P0级的磁盘清空问题复盘

事件背景

一个小伙伴开开心心写了一段文件夹删除代码,不过在自测的时候出现了事故。
整个C盘文件被一扫而空,不得不重装系统,珍藏资料也难以找回。


问题排查

先上源码。警告:此源码切勿运行

#include <string>

std::wstring dirBackSlashAlign(const std::wstring& strDir)
{
    std::wstring strTemp = strDir;

    if (!strTemp.empty() && strTemp.back() != L'\\') {
        strTemp.push_back(L'\\');
    }

    return strTemp;
}

void deleteDirRecursively(const std::wstring& dirName)
{
    std::wstring strDirName = dirBackSlashAlign(dirName);
    std::wstring strFindFiles = strDirName + L"*";

    WIN32_FIND_DATA fd;
    HANDLE hFind = FindFirstFile(strFindFiles.c_str(), &fd);

    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            std::wstring strFindFile = fd.cFileName;
            if (strFindFile == L".." || strFindFile == L".") continue;

            strFindFile = strDirName + strFindFile;
            if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                deleteDirRecursively(strFindFile);
            }
            else {
                //防止误运行,此代码做屏蔽
                //::SetFileAttributes(strFindFile.c_str(), FILE_ATTRIBUTE_NORMAL);
                //::DeleteFile(strFindFile.c_str());
            }
        } while (FindNextFile(hFind, &fd));

        FindClose(hFind);
        hFind = INVALID_HANDLE_VALUE;
    }

    //防止误运行,此代码做屏蔽
    //::SetFileAttributes(dirName.c_str(), FILE_ATTRIBUTE_NORMAL);
    //::RemoveDirectory(dirName.c_str());
}

void RunTest()
{
    deleteDirRecursively(L"\\");
}

问题出在哪里呢?一步步推断看下。

  • 删除函数本身正常
  • 拿掉删除函数,进行调式发现遍历出了问题,对根目录做了递归遍历
  • 为什么是根目录呢,入参传入了\,这个意思就是根目录
  • 好了,破案了,传参误传了
  • 这就好比是linux下进入到根目录,执行rm -rf,都是泪呀
  • 如果传入的是空字符串呢,那就等于在当前目录执行rm -rf,也是泪呀

问题修复

知道了问题原因,就可以做修复了,做下入参有效性判断。
代码如下。

#include "Shlwapi.h"
#pragma comment(lib,"shlwapi.lib")

void deleteDirRecursively(const std::wstring& dirName)
{
	//添加有效性检查
    if (!PathFileExists(dirName.c_str()))
        return;

    if (L"\\" == dirName)
        return;
    //...
}

问题总结

针对这次P0级别的问题修复,对函数入参做防御性有效性判断永远都是对的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值