Repository navigation
Conversation
1. Root cause: DTK DPrintPreviewDialog sets printer output file path without checking directory write permission, QPainter construction on unwritable QPrinter creates null engine, setClipRect dereferences null pointer causing SIGSEGV 2. Fix: add directory writability check at start of both onPrintRequested overloads using QTemporaryFile probe, redirect to temp directory with DDialog warning when unwritable 3. Impact: only affects save-to-PDF with unwritable target directory, normal writable paths have no behavior change Log: Fix crash when saving PDF to directory without write permission Influence: 1. Test save PDF to writable directory (normal path) 2. Test save PDF to unwritable directory (should show dialog, no crash) 3. Test normal printing to physical printer (unaffected) fix: 修复保存PDF到无权限目录时崩溃的问题 1. 根因:DTK DPrintPreviewDialog 设置打印输出文件路径时未检查 目录写权限,QPrinter 在不可写路径上构造 QPainter 时引擎为空, setClipRect 解引用空指针导致 SIGSEGV 2. 方案:在两个 onPrintRequested 重载开头用 QTemporaryFile 探测 目录写权限,不可写时弹出 DDialog 提示并重定向到临时目录 3. 影响:仅影响保存PDF到不可写目录的场景,正常可写路径无行为变化 Log: 修复保存PDF到无权限目录时崩溃的问题 Influence: 1. 测试保存PDF到可写目录(正常路径) 2. 测试保存PDF到不可写目录(应弹出提示,不崩溃) 3. 测试正常打印到物理打印机(不受影响) PMS: BUG-380945
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: LiHua000 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Reviewer's GuideThe PR prevents PDF-printing crashes caused by unwritable output directories by probing directory access before painting and redirecting failures to a temporary location, while also adding localized Document Viewer user guides. Sequence diagram for safe PDF printing to an unwritable directorysequenceDiagram
actor User
participant DocSheet
participant QTemporaryFile
participant DDialog
participant QPrinter
participant QPainter
participant TempLocation
User->>DocSheet: onPrintRequested(printer)
DocSheet->>QPrinter: outputFileName()
alt output path is unwritable
DocSheet->>QTemporaryFile: open()
QTemporaryFile-->>DocSheet: failure
DocSheet->>DDialog: exec()
DDialog-->>DocSheet: accepted
DocSheet->>TempLocation: writableLocation(TempLocation)
TempLocation-->>DocSheet: temporary directory
DocSheet->>QPrinter: setOutputFileName(temp path)
else output path is writable or empty
DocSheet->>QTemporaryFile: open()
QTemporaryFile-->>DocSheet: success or skipped
end
DocSheet->>QPainter: QPainter(printer)
QPainter-->>DocSheet: painter constructed without crash
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
deepin pr auto review🤖 AI 代码审查报告📊 总体评价
🔍 详细分析1. 语法逻辑 ✅评价: 语法正确,逻辑清晰 ✅ 通过 潜在问题: 建议: [] 2. 代码质量 ✅评价: 代码结构清晰,注释完整 ✅ 通过 潜在问题: 建议: ['将重复的权限检查和重定向逻辑提取为辅助方法,例如:void DocSheet::ensureOutputDirWritable(DPrinter *printer),在两个 onPrintRequested 重载中调用', '简化字符串拼接:将 QString("dr_") + "exception-logo" 改为 QStringLiteral("dr_exception-logo")'] 3. 代码性能 ✅评价: 性能良好,资源使用合理 ✅ 通过 潜在问题: 建议: [] 4. 代码安全 🔒评价: 存在0个安全漏洞 ✅ 通过
安全漏洞详情: 建议: [] 💡 改进建议代码示例// 建议提取公共辅助方法,消除代码重复: // // void DocSheet::ensureOutputDirWritable(DPrinter *printer) // { // QString outputPath = printer->outputFileName(); // if (outputPath.isEmpty()) // return; // // QString dir = QFileInfo(outputPath).absolutePath(); // QTemporaryFile testFile(dir + "/.dr_print_test_XXXXXX"); // if (testFile.open()) // return; // // qCWarning(appLog) << "Output directory not writable:" << dir // << ", redirecting to temp"; // DDialog dlg("", tr("The selected directory does not have write permission. " // "The file will be saved to the temporary directory.")); // dlg.setIcon(QIcon::fromTheme(QStringLiteral("dr_exception-logo"))); // dlg.addButtons(QStringList() << tr("OK", "button")); // QMargins mar(0, 0, 0, 30); // dlg.setContentLayoutContentsMargins(mar); // dlg.exec(); // // QString tempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation); // printer->setOutputFileName(tempDir + "/" + QFileInfo(outputPath).fileName()); // }本报告由 AI 代码审查工具自动生成 |
Root Cause Analysis
DTK
DPrintPreviewDialogPrivate::_q_startPrintsets the printer output file path viaprinter->setOutputFileName(str)without checking directory write permission. When the target directory is not writable,DPrintPreviewWidget::asynPrint()constructsQPainter painter(previewPrinter)which fails (QPrinter cannot open the file, print engine is null). The subsequentpainter.setClipRect()dereferences the null engine pointer at offset 0x1c, causing SIGSEGV. Core dump signalsigno=11, si_addr=0x1cconfirms this path.Key evidence:
dprintpreviewdialog.cpp:2504(setOutputFileName without permission check),dprintpreviewwidget.cpp:215(QPainter construction on unwritable QPrinter),dprintpreviewwidget.cpp:221(setClipRect dereference crash point).Fix
Added directory writability check at the start of both
DocSheet::onPrintRequestedoverloads usingQTemporaryFileprobe. When the directory is not writable, aDDialogwarning is shown and the output path is redirected toQStandardPaths::TempLocation. This ensures QPainter construction succeeds, preventing the crash. Normal writable paths have no behavior change.The root cause fix (DTK-side permission check before
setOutputFileName) was not feasible because the dtkwidget repository is not available in the current workspace. Subclassing/event-filteringDPrintPreviewDialogwas also not feasible (_q_startPrintis a private non-virtual slot with no interceptable signal between file dialog return andpview->print()). ThepaintRequestedsignal callback was used instead, as it fires afteroutputFileName()is set but before the crash path.Change Safety Assessment
Code Safety
onPrintRequestedoverloads are connected viapaintRequestedsignal inonPopPrintDialog()— connection relationships unchangedBusiness Impact Scope
Verification Suggestion
/root) — confirm dialog appears and no crash根因分析
DTK
DPrintPreviewDialogPrivate::_q_startPrint在用户选择保存路径后直接调用printer->setOutputFileName(str)而不检查目录写权限。当目录不可写时,DPrintPreviewWidget::asynPrint()中QPainter painter(previewPrinter)构造失败(QPrinter 无法打开文件,打印引擎为空),随后painter.setClipRect()解引用空引擎指针(偏移 0x1c),导致 SIGSEGV。core dump 信号signo=11, si_addr=0x1c与此路径吻合。关键证据:
dprintpreviewdialog.cpp:2504(setOutputFileName 无权限检查)、dprintpreviewwidget.cpp:215(QPrinter 不可写时 QPainter 构造失败)、dprintpreviewwidget.cpp:221(setClipRect 解引用空指针崩溃点)。修复方案
在
DocSheet::onPrintRequested两个重载函数开头,用QTemporaryFile探测输出目录写权限。不可写时弹出DDialog提示并重定向到QStandardPaths::TempLocation,使 QPainter 构造成功,避免崩溃。正常可写路径无行为变化。根因层修复(DTK 侧 setOutputFileName 前加权限检查)因 dtkwidget 仓库不在当前工作区不可行。子类化/事件过滤 DPrintPreviewDialog 也不可行(
_q_startPrint为私有非虚槽,文件对话框返回与pview->print()之间无可拦截信号)。实际改用paintRequested信号回调中检查写权限并重定向。改动安全评估
代码安全评估
onPrintRequested重载由onPopPrintDialog()中paintRequested信号连接,连接关系不变业务影响范围
验证建议
/root),确认弹出提示对话框且不崩溃PMS: BUG-380945
Summary by Sourcery
Prevent unwritable PDF export locations from crashing the application and add localized Document Viewer documentation.
Bug Fixes:
Documentation: