From 313ac489e85abbeabb5fc136c95654e28e661f8a Mon Sep 17 00:00:00 2001 From: Liu Jinchang Date: Mon, 15 Sep 2025 17:47:42 +0800 Subject: [PATCH] fix: resolve dangling pointer in filePath MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Root cause: DEnumeratorPrivate::filePath() returned toUtf8().data()/toLatin1().data() from temporary QByteArray, causing dangling pointer after function return 2. Fix: change filePath() to return QByteArray by value, ensuring RAII lifetime; openDirByfts() wraps result with strdup() for fts_open, sortFileInfoList() uses constData() directly 3. Impact: eliminates dangling pointer and manual free() in sortFileInfoList(), fixing incorrect file counts in directory traversal; remove unused stdio.h include in dfm-list Log: Fix incorrect directory traversal file counts caused by dangling pointer in filePath Influence: 1. Test directory enumeration returns correct file counts 2. Test directory traversal with special characters in paths 3. Verify no memory leaks in filePath and sortFileInfoList fix: 修复 filePath 悬垂指针导致目录遍历文件计数错误 1. 根因:DEnumeratorPrivate::filePath() 通过 toUtf8().data()/ toLatin1().data() 返回临时 QByteArray 的内部指针,函数返回 后临时对象销毁产生悬垂指针 2. 方案:将 filePath() 返回类型改为 QByteArray(按值返回),利用 RAII 管理生命周期;openDirByfts() 用 strdup() 包装供 fts_open 使用,sortFileInfoList() 直接使用 constData() 3. 影响:消除 sortFileInfoList() 中的悬垂指针和手动 free(), 修复目录遍历文件计数不正确的问题 Log: 修复目录遍历文件计数不正确的问题 Influence: 1. 测试目录遍历返回正确的文件数量 2. 测试包含特殊字符路径的目录遍历 3. 验证 filePath 和 sortFileInfoList 无内存泄漏 PMS: BUG-380499 BUG-333909 --- src/dfm-io/dfm-io/denumerator.cpp | 17 ++++++----------- src/dfm-io/dfm-io/private/denumerator_p.h | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/dfm-io/dfm-io/denumerator.cpp b/src/dfm-io/dfm-io/denumerator.cpp index 03091610..17f633d6 100644 --- a/src/dfm-io/dfm-io/denumerator.cpp +++ b/src/dfm-io/dfm-io/denumerator.cpp @@ -302,7 +302,7 @@ bool DEnumeratorPrivate::checkNameFilter(const QString &fileName) bool DEnumeratorPrivate::openDirByfts() { char *paths[2] = { nullptr, nullptr }; - paths[0] = filePath(uri); + paths[0] = strdup(filePath(uri).constData()); if (!paths[0]) { error.setCode(DFMIOErrorCode::DFM_IO_ERROR_FAILED); return false; @@ -433,15 +433,15 @@ void DEnumeratorPrivate::setQueryAttributes(const QString &attributes) queryAttributes = attributes; } -char *DEnumeratorPrivate::filePath(const QUrl &url) +QByteArray DEnumeratorPrivate::filePath(const QUrl &url) { if (url.userInfo().startsWith("originPath::")) - return strdup(url.userInfo().replace("originPath::", "").toLatin1().constData()); + return url.userInfo().replace("originPath::", "").toLatin1(); QString path = url.path(); if (path != "/" && path.endsWith("/")) path = path.left(path.length() - 1); - return strdup(path.toUtf8().constData()); + return path.toUtf8(); } QUrl DEnumeratorPrivate::buildUrl(const QUrl &url, const char *fileName) @@ -831,11 +831,8 @@ QList> DEnumerator::sortFileInfoList() QSet hideList; QUrl urlHidden = d->buildUrl(d->uri, ".hidden"); hideList = DLocalHelper::hideListFromUrl(urlHidden); - char *dirPath = d->filePath(d->uri); - if (!dirPath) { - qWarning() << "Failed to get file path for uri:" << d->uri; - return {}; - } + QByteArray dirPathBa = d->filePath(d->uri); + const char *dirPath = dirPathBa.constData(); while (1) { FTSENT *ent = fts_read(d->fts); @@ -857,8 +854,6 @@ QList> DEnumerator::sortFileInfoList() fts_close(d->fts); d->fts = nullptr; - // Clean up allocated memory - free(dirPath); if (d->isMixDirAndFile) return listFile; diff --git a/src/dfm-io/dfm-io/private/denumerator_p.h b/src/dfm-io/dfm-io/private/denumerator_p.h index d8b5efd0..4a8c8295 100644 --- a/src/dfm-io/dfm-io/private/denumerator_p.h +++ b/src/dfm-io/dfm-io/private/denumerator_p.h @@ -55,7 +55,7 @@ class DEnumeratorPrivate : public QObject, public QEnableSharedFromThis> fileInfoList(); void setQueryAttributes(const QString &attributes); - char *filePath(const QUrl &url); + QByteArray filePath(const QUrl &url); QUrl buildUrl(const QUrl &url, const char *fileName); static void enumUriAsyncCallBack(GObject *sourceObject,