Skip to content

fix(excel): fix segfault on xlsx with main content type declared via …#61

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
pppanghu77:master
Jun 22, 2026
Merged

fix(excel): fix segfault on xlsx with main content type declared via …#61
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
pppanghu77:master

Conversation

@pppanghu77

@pppanghu77 pppanghu77 commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

  • Wrap the branch in iterate_files_by_contenttype_expat_callback_element_start (xlsxio_read.c) with #ifndef USE_MINIZIP so the minizip backend skips the zip directory traversal at compile time; previously the traversal ran inside an expat callback while [Content_Types].xml was open for streaming read, reentering the minizip single-state handle and crashing in unzGetCurrentFileInfo (upstream issue feat: add build depends libfreetype-dev #28, unfixed in xlsxio 0.2.36)
  • Add regression sample tests/file/test_xlsxio_default_crash.xlsx whose [Content_Types].xml declares the main content type via to cover the former crash path

修复(excel): 修复 main contenttype 经 声明的 xlsx 解析段错误

  • 在 iterate_files_by_contenttype_expat_callback_element_start 的 分支用 #ifndef USE_MINIZIP 包裹,使 minizip 后端编译期跳过 zip 目录遍历;原实现该遍历在 expat 回调内执行,而此时 [Content_Types].xml 已打开流式读取,对同一 unzFile 重入导致 minizip 单状态机冲突,在 unzGetCurrentFileInfo 处段错误(上游 issue feat: add build depends libfreetype-dev #28,xlsxio 0.2.36 未修复)
  • 新增回归样本 tests/file/test_xlsxio_default_crash.xlsx,其 [Content_Types].xml 将 main contenttype 经 声明,覆盖原崩溃路径

Log: 修复 xlsxio 在 minizip 后端下解析 [Content_Types].xml 中经 声明的 main contenttype 时,因目录遍历重入已打开文件的流式读取状态而在 unzGetCurrentFileInfo 处段错误的问题,并补充回归样本
Task: https://pms.uniontech.com/task-view-391297.html brechtsanders/xlsxio#28

Summary by Sourcery

Prevent crashes when parsing XLSX content types with main type declared via using the minizip backend and add regression coverage.

Bug Fixes:

  • Skip zip directory traversal for content type entries when building with the minizip backend to avoid reentering the same unzFile and triggering a segfault.

Tests:

  • Add regression XLSX fixture where [Content_Types].xml declares the main content type via to cover the former crash path.

…<Default>

- Wrap the <Default> branch in iterate_files_by_contenttype_expat_callback_element_start (xlsxio_read.c) with #ifndef USE_MINIZIP so the minizip backend skips the zip directory traversal at compile time; previously the traversal ran inside an expat callback while [Content_Types].xml was open for streaming read, reentering the minizip single-state handle and crashing in unzGetCurrentFileInfo (upstream issue linuxdeepin#28, unfixed in xlsxio 0.2.36)
- Add regression sample tests/file/test_xlsxio_default_crash.xlsx whose [Content_Types].xml declares the main content type via <Default> to cover the former crash path

修复(excel): 修复 main contenttype 经 <Default> 声明的 xlsx 解析段错误

- 在 iterate_files_by_contenttype_expat_callback_element_start 的 <Default> 分支用 #ifndef USE_MINIZIP 包裹,使 minizip 后端编译期跳过 zip 目录遍历;原实现该遍历在 expat 回调内执行,而此时 [Content_Types].xml 已打开流式读取,对同一 unzFile 重入导致 minizip 单状态机冲突,在 unzGetCurrentFileInfo 处段错误(上游 issue linuxdeepin#28,xlsxio 0.2.36 未修复)
- 新增回归样本 tests/file/test_xlsxio_default_crash.xlsx,其 [Content_Types].xml 将 main contenttype 经 <Default> 声明,覆盖原崩溃路径

Log: 修复 xlsxio 在 minizip 后端下解析 [Content_Types].xml 中经 <Default> 声明的 main contenttype 时,因目录遍历重入已打开文件的流式读取状态而在 unzGetCurrentFileInfo 处段错误的问题,并补充回归样本
Task: https://pms.uniontech.com/task-view-391297.html brechtsanders/xlsxio#28
@sourcery-ai

sourcery-ai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Wrap the handler in iterate_files_by_contenttype_expat_callback_element_start with a USE_MINIZIP guard to avoid re-entering the minizip unzip state machine while [Content_Types].xml is being streamed, and add a regression XLSX sample exercising this former crash path.

Sequence diagram for expat callback handling of Default with minizip versus libzip

sequenceDiagram
  participant Reader
  participant Minizip
  participant Libzip
  participant Expat
  participant IterateCallback

  Reader->>Minizip: unzOpenCurrentFile
  Reader->>Expat: expat_process_zip_file
  Expat->>IterateCallback: iterate_files_by_contenttype_expat_callback_element_start

  alt libzip_backend
    IterateCallback->>Libzip: zip_get_name
  end

  alt minizip_backend_before_fix
    IterateCallback->>Minizip: unzGoToFirstFile
    IterateCallback->>Minizip: unzGetCurrentFileInfo
    IterateCallback->>Minizip: unzGoToNextFile
  end

  alt minizip_backend_after_fix
    Note over IterateCallback: [Default branch skipped when USE_MINIZIP]
  end
Loading

File-Level Changes

Change Details Files
Prevent minizip backend from traversing ZIP directory for content types during [Content_Types].xml streaming, avoiding a segfault.
  • Add commentary explaining that, under the minizip backend, [Content_Types].xml is already opened via unzOpenCurrentFile when the expat callback runs, and that reusing the same unzFile with directory traversal APIs causes a crash.
  • Wrap the branch of iterate_files_by_contenttype_expat_callback_element_start in an #ifndef USE_MINIZIP so that only the libzip backend continues to perform extension-based matching.
  • Add a closing #endif comment clarifying that the branch is skipped under USE_MINIZIP to avoid minizip state conflicts.
3rdparty/libs/fileext/excel/xlsxio/xlsxio_read.c

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions

Copy link
Copy Markdown
  • 敏感词检查失败, 检测到1个文件存在敏感词
详情
{
    "3rdparty/libs/fileext/excel/xlsxio/xlsxio_read.c": [
        {
            "line": "        if (XML_Char_icmp(reltype, X(\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\")) == 0) {",
            "line_number": 853,
            "rule": "S35",
            "reason": "Url link | 591ded0820"
        },
        {
            "line": "        } else if (XML_Char_icmp(reltype, X(\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings\")) == 0) {",
            "line_number": 861,
            "rule": "S35",
            "reason": "Url link | b67c93b15a"
        },
        {
            "line": "        } else if (XML_Char_icmp(reltype, X(\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\")) == 0) {",
            "line_number": 866,
            "rule": "S35",
            "reason": "Url link | 7b6758f750"
        }
    ]
}

@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.

Hey - I've left some high level feedback:

  • The backend-specific logic is embedded directly in the XML callback with #ifndef USE_MINIZIP; consider centralizing backend differences behind a small helper or abstraction so the parsing callback remains backend-agnostic and easier to reason about.
  • The new block comment around the #ifndef USE_MINIZIP and the long #endif trailing comment are quite verbose and language-mixed; consider shortening and standardizing them (e.g., English-only, with a brief explanation and an upstream issue reference) to keep the code easier to scan.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The backend-specific logic is embedded directly in the XML callback with `#ifndef USE_MINIZIP`; consider centralizing backend differences behind a small helper or abstraction so the parsing callback remains backend-agnostic and easier to reason about.
- The new block comment around the `#ifndef USE_MINIZIP` and the long `#endif` trailing comment are quite verbose and language-mixed; consider shortening and standardizing them (e.g., English-only, with a brief explanation and an upstream issue reference) to keep the code easier to scan.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:100分

■ 【总体评价】

代码通过条件编译精准修复了minizip后端解析xlsx文件时的段错误崩溃问题,注释详尽且逻辑严密。
四个审查维度均表现优异,无任何语法缺陷、质量瑕疵、性能损耗或安全风险,属于高质量的第三方库缺陷修复补丁。

■ 【详细分析】

  • 1.语法逻辑 完全正确✓

iterate_files_by_contenttype_expat_callback_element_start 函数中使用 #ifndef USE_MINIZIP ... #endif 宏包裹原有逻辑,语法完全正确。该方案精准隔离了 minizip 单状态机下调用 unzGoToFirstFile 等遍历函数导致的上下文破坏,同时完整保留了 libzip 后端基于索引的正常处理逻辑,条件分支互斥且完备。
潜在问题:无
建议:无

  • 2.代码质量 优秀✓

补丁注释极其详尽,不仅指出了报错现象(段错误)、根本原因(minizip 单状态机被破坏)、上游状态(issue #28 及 0.2.36 版本未修复),还从 xlsx 文件格式规范层面论证了跳过该分支的业务合理性(合法 xlsx 必须通过 <Override> 声明 main contenttype),极大降低了后续维护人员的理解成本。
潜在问题:无
建议:无

  • 3.代码性能 高效✓

通过预处理器宏在编译期直接裁剪掉了 minizip 后端下无意义的文件遍历逻辑,避免了在流式解析 [Content_Types].xml 期间触发无效且致命的 unzGoToFirstFile / unzGetCurrentFileInfo 等耗时操作,属于零开销的防御性编程。
潜在问题:无
建议:无

  • 4.代码安全 存在0个安全漏洞✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
本次修改成功消除了解析恶意或特殊构造的 xlsx 文件时触发的段错误(拒绝服务风险),未引入任何新的内存越界、空指针解引用或注入类安全漏洞。
建议:无

■ 【改进建议代码示例】

--- a/3rdparty/libs/fileext/excel/xlsxio/xlsxio_read.c
+++ b/3rdparty/libs/fileext/excel/xlsxio/xlsxio_read.c
@@ -684,6 +684,13 @@ void iterate_files_by_contenttype_expat_callback_element_start (void* callbackda
     }
   } else if (XML_Char_icmp_ins(name, X("Default")) == 0) {
     //by extension
+    // minizip 后端下:外层 expat_process_zip_file 已 unzOpenCurrentFile 打开
+    // [Content_Types].xml 并流式读取,此处对同一 unzFile 调用 unzGoToFirstFile /
+    // unzGetCurrentFileInfo / unzGoToNextFile 会破坏 minizip 单状态机导致段错误
+    // (上游 issue #28,xlsxio 0.2.36 仍未修复)。合法 xlsx 的 main contenttype 必
+    // 通过 <Override> 声明,<Default> 扩展名匹配对 xlsxio 无意义,故 minizip 后端
+    // 直接跳过本分支;libzip 后端基于索引的 zip_get_name 不受影响,逻辑保留。
+#ifndef USE_MINIZIP
     const XML_Char* contenttype;
     const XML_Char* extension;
     if ((contenttype = get_expat_attr_by_name(atts, X("ContentType"))) != NULL && XML_Char_icmp(contenttype, data->contenttype) == 0) {
@@ -731,6 +738,7 @@ unzGetGlobalInfo(data->zip, &zipglobalinfo);
 #endif
       }
     }
+#endif /* !USE_MINIZIP: 跳过 <Default> 分支,避免 minizip 状态冲突崩溃 */
   }
 }

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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

@pppanghu77

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot

deepin-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

This pr force merged! (status: unstable)

@deepin-bot
deepin-bot Bot merged commit 4ac50cd into linuxdeepin:master Jun 22, 2026
22 of 23 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