Skip to content

fix: prevent BOM character loss in path concatenation#322

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:develop/eaglefrom
liyigang1:develop/eagle
Jun 24, 2026
Merged

fix: prevent BOM character loss in path concatenation#322
deepin-bot[bot] merged 1 commit into
linuxdeepin:develop/eaglefrom
liyigang1:develop/eagle

Conversation

@liyigang1

Copy link
Copy Markdown
Contributor

Use std::string for directory path concatenation to avoid QString's normalization of UTF-8 BOM (U+FEFF / zero-width no-break space).

使用 std::string 进行路径拼接,避免 QString 对 UTF-8 BOM
(零宽不换行空格) 的规范化导致字节丢失。

Log: 修复路径拼接时 BOM 字符丢失的问题
Bug: https://pms.uniontech.com//bug-view-367075.html
Influence: 修复后包含 BOM/零宽不换行空格的路径能正确拼接,避免文件操作失败。

Use std::string for directory path concatenation to avoid QString's
normalization of UTF-8 BOM (U+FEFF / zero-width no-break space).

使用 std::string 进行路径拼接,避免 QString 对 UTF-8 BOM
(零宽不换行空格) 的规范化导致字节丢失。

Log: 修复路径拼接时 BOM 字符丢失的问题
Bug: https://pms.uniontech.com//bug-view-367075.html
Influence: 修复后包含 BOM/零宽不换行空格的路径能正确拼接,避免文件操作失败。

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @liyigang1, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

用户要求对提供的代码diff进行深度审核,并严格按照指定格式输出报告。 提供的diff是对`src/dfm-io/dfm-io/denumerator.cpp`中`DEnumeratorPrivate::buildUrl`函数的修改。

分析diff:
原代码:

QUrl DEnumeratorPrivate::buildUrl(const QUrl &url, const char *fileName)
{
    QString path;
    if (url.path() == "/") {
        path = "/" + QString(fileName);
    } else {
        QString dirPath = url.path();
        path = dirPath.endsWith('/') ? dirPath + QString(fileName) : dirPath + "/" + QString(fileName);
    }
    // ...

新代码:

QUrl DEnumeratorPrivate::buildUrl(const QUrl &url, const char *fileName)
{
    // 防御空指针,避免std::string或QByteArray构造时崩溃
    if (!fileName) {
        return QUrl();
    }

    // 拦截路径遍历攻击,防止恶意文件名越权
    QByteArray fileNameBa(fileName);
    // 拦截路径遍历攻击:禁止文件名中包含任何路径分隔符或连续点号,从根源阻断目录穿越
    if (fileNameBa.contains('/') || fileNameBa.contains('\\') || fileNameBa == "." || fileNameBa == "..") {
        return QUrl();
    }

    QByteArray path;
    QString urlPath = url.path();

    if (urlPath == "/" || urlPath.isEmpty()) {
        path = QByteArray("/") + fileNameBa;
    } else {
        QByteArray dirPath = urlPath.toUtf8();
        if (!dirPath.endsWith('/')) {
            dirPath.append('/');
        }
        // 使用QByteArray进行底层字节数组拼接,避免QString剥离BOM (efbbbf)
        path = dirPath + fileNameBa;
    }

    // 保留原始 URL 的 scheme 和 host,而不是假定为本地文件
  1. 语法逻辑:
  • 新增了!fileName的空指针检查,逻辑正确。
  • 路径遍历检查:fileNameBa.contains('/') || fileNameBa.contains('\\') || fileNameBa == "." || fileNameBa == ".."
    • 这个检查有问题:如果fileNameBa"../etc/passwd",它包含/,会被拦截。
    • 如果fileNameBa"....",它不等于...,也不包含/\,会绕过检查。虽然....不是标准的路径遍历,但在某些文件系统或特定解析器中可能被特殊处理,但作为常规防御,可以接受。
    • 更重要的是,如果文件名是"a..b",它不等于..,不包含/\,通过检查。这是正常的。
    • 但是如果文件名是"..",被拦截了。
    • 有没有漏洞?如果文件名是" . . "或者".."带空格?不过QByteArray直接比较"..",带空格不会匹配。
    • 整体语法逻辑上没有明显的编译错误或内存泄漏。标记为✓,评价词"正确"。
  1. 代码质量:
  • 注释比较详细,解释了为什么做这些修改(防御空指针、拦截路径遍历、避免QString剥离BOM)。
  • 变量命名清晰:fileNameBa, urlPath, dirPath
  • 逻辑清晰,拆分了if-else,可读性提高。
  • 标记为✓,评价词"良好"。
  1. 代码性能:
  • 原来使用QString拼接,现在使用QByteArray拼接。
  • QByteArray拼接比QString在某些情况下(特别是纯ASCII或需要保留

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: liyigang1, max-lvs

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@liyigang1

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot deepin-bot Bot merged commit 6514ce2 into linuxdeepin:develop/eagle Jun 24, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants