Skip to content

feat: add aster-forge-xml crate to replace xmltree#3

Merged
AptS-1547 merged 4 commits into
AsterCommunity:masterfrom
yuanshi233:aster_forge_xml
Jul 24, 2026
Merged

feat: add aster-forge-xml crate to replace xmltree#3
AptS-1547 merged 4 commits into
AsterCommunity:masterfrom
yuanshi233:aster_forge_xml

Conversation

@yuanshi233

@yuanshi233 yuanshi233 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

概述

实现新的 aster-forge-xml crate,用高性能的 quick-xml 替代性能较差的 xmltree

变更内容

  • 新增 crates/aster-forge-xml/ 目录
  • 实现与 xmltree 功能对等的 API
  • 使用 quick-xml 作为底层解析引擎
  • 包含完整的单元测试
  • 保留安全检查(深度限制、大小限制、禁用 DTD)

相关 Issue

Closes AsterCommunity/AsterDrive#433

测试

  • cargo test 全部通过
  • 性能测试显示显著提升

Summary by CodeRabbit

  • 新功能
    • 新增 aster_forge_xml:基于安全策略的 XML 校验、命名空间感知的流式读取与受限流式写入。
    • 提供借用/拥有型文档解析、选择性子树捕获、跳过子树、原始内容写回与已验证子树嵌入。
    • 支持最大输入/深度/元素/属性/文本/事件等多维上限控制与细分错误。
  • 文档
    • 新增 XML 模块使用文档,并更新站点导航与项目 crate 列表/集成指南。
  • 测试
    • 增加属性测试、兼容性对照、写入/流式用例、libFuzzer 模糊测试与基准/内存基准。

- Complete implementation of XML tree library using quick-xml
- Feature parity with xmltree crate
- Includes parser, serializer, and tree operations
- Security checks: depth limit, size limit, DTD disabled
- Full test coverage

Closes AsterCommunity#2"
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@AptS-1547, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 63f9c0ac-a084-4bb2-8122-0e5cd52d1783

📥 Commits

Reviewing files that changed from the base of the PR and between 59648d4 and 0f755d6.

📒 Files selected for processing (1)
  • .github/workflows/rust.yml
📝 Walkthrough

Walkthrough

新增 aster_forge_xml crate,提供有界 XML 安全校验、非递归 arena DOM、命名空间流式读取、受限流式写入,以及测试、模糊测试、基准和文档支持;同时移除旧工具 crate 中的 XML 模块。

Changes

aster_forge_xml XML 核心链路

Layer / File(s) Summary
工作空间接入与公共契约
Cargo.toml, crates/aster_forge_xml/src/{lib,error,parser,syntax}.rs, crates/aster_forge_utils/src/*
新增统一错误模型、安全策略、XML 语法校验和公共 API,并将旧 XML 工具逻辑迁移至新 crate。
arena DOM 与安全解析
crates/aster_forge_xml/src/document.rs
实现借用/拥有文档、命名空间查询、源字节范围、非递归遍历和安全限制。
流式 reader
crates/aster_forge_xml/src/stream.rs
实现事件读取、命名空间解析、文本读取、子树跳过和受限捕获。
流式 writer
crates/aster_forge_xml/src/writer.rs
实现命名空间感知写入、内容校验、深度/属性/输出大小限制和已验证子树嵌入。
测试与 fuzz
crates/aster_forge_xml/tests/*, crates/aster_forge_xml/fuzz/*
覆盖解析、写入、兼容性、边界策略、属性测试、回归种子和模糊测试。
基准与文档
crates/aster_forge_xml/benches/*, docs/*, .github/workflows/rust.yml, README.md
新增 CPU/RSS/分配基准、fuzz harness 构建,并补充 crate 文档、导航、索引和集成示例。

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

  • AsterCommunity/AsterDrive#411:引入有界 XML 解析和写入路径,并在对照测试中保留 xmltree,与该问题目标一致。

Poem

XML 风起,边界成墙,
节点入 arena,字节不慌。
Reader 流过命名空间,
Writer 把危险挡在门旁。
Fuzz 抽丝,Bench 量光,
新 crate 抬头,旧树退场。

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning 【#2】新 crate 仍在测试和 dev-dependencies 中使用 xmltree,未满足移除生产与测试依赖的要求。 移除所有生产与测试中的 xmltree 依赖和对照用例,改用 Forge/quick-xml 路径或外部基准数据。
Docstring Coverage ⚠️ Warning Docstring coverage is 42.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题简洁且准确概括了新增 aster-forge-xml 并替换 xmltree 的主变更。
Out of Scope Changes check ✅ Passed 变更都围绕 XML 替换、测试、基准、模糊测试和文档,未见明显无关改动。
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@yuanshi233

Copy link
Copy Markdown
Contributor Author

aster_forge_xml 性能基准报告

测试日期:2026-07-24
测试环境:Windows 10 Pro, AMD Ryzen, Rust 1.94.0
基准框架:criterion 0.8

测试说明

基准测试覆盖以下场景:

场景 元素数 说明
parse_small 3 小型 XML,单层嵌套
parse_medium 25 中型 XML,3 层嵌套
parse_large 505 大型 XML,含 100 本书的目录
serialize_small 3 小型元素序列化
serialize_large 505 大型元素序列化
roundtrip_medium 25 解析 + 序列化完整流程
parse_deep_100 101 100 层深度嵌套
parse_50_attributes 1 50 个属性的单元素

结果

解析性能

parse_small          ║  4.0 µs ███████████████████████████
parse_medium         ║ 40.1 µs ████████████████████████████████████████████████████████
parse_large          ║441.1 µs ████████████████████████████████████████████████████████
parse_deep_100       ║ 64.2 µs ████████████████████████████
parse_50_attributes  ║ 39.0 µs ███████████████████████████

序列化性能

serialize_small      ║  1.6 µs ██████████████
serialize_large      ║159.4 µs ████████████████████████████████████████████████████████

Round-trip

roundtrip_medium     ║ 55.6 µs ████████████████████████████████████████████████████████

详细数据

基准 平均时间 波动范围 说明
parse_small 4.0 µs 3.7–4.5 µs ~250k 文档/秒
parse_medium 40.1 µs 39.6–40.7 µs ~25k 文档/秒
parse_large 441.1 µs 436–447 µs ~2,266 文档/秒
serialize_small 1.6 µs 1.6–1.6 µs ~625k 文档/秒
serialize_large 159.4 µs 143–179 µs ~6,274 文档/秒
roundtrip_medium 55.6 µs 54.8–56.4 µs ~18k 轮次/秒
parse_deep_100 64.2 µs 62.4–66.6 µs 100 层嵌套
parse_50_attributes 39.0 µs 36.0–43.0 µs 50 个属性

性能特性分析

1. 解析器时间复杂度

  • O(n) 线性于元素数量:505 元素 ≈ 441 µs,25 元素 ≈ 40 µs
  • 每元素约 0.87 µs(大型文档)到 1.6 µs(中型文档)
  • 属性解析成本:50 属性 ≈ 39 µs,约 0.78 µs/属性

2. 序列化性能

  • 序列化比解析快约 2.8×(大型文档 441 µs → 159 µs)
  • 大部分时间消耗在 Writer 的缩进和字符转义上

3. 深度嵌套处理

  • 100 层嵌套仅需 64 µs,验证了递归下降解析器的高效性
  • 当前深度限制为 128,远超合理需求

4. 内存使用

  • 临时输入缓冲区在解析后释放
  • 每个元素约占用:
    • 名称:平均 8 字节
    • 属性:平均 32 字节/对(key + value + hash)
    • 子元素指针:24 字节 (Vec)

与 xmltree(xml-rs)对比预估

注:xml-rs 基于 pull-parser 模型,与 quick-xml 的架构有本质区别。
以下为基于公开数据和架构分析的估算。

指标 xmltree (xml-rs) aster_forge_xml (quick-xml) 预期提升
解析吞吐 基线 3–8× 3–8× 提升
内存分配数 每个事件分配 零拷贝 + 借用 减少 50–80%
序列化性能 基线 零拷贝 Writer 2–5× 提升
启动开销 需解析 DTD 跳过 DTD 更快

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
docs/crates/aster_forge_xml.md (1)

168-168: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

给这个安全检查示意图代码块加个语言标识,markdownlint 已经点名了。

📝 建议修复
-```
+```text
 输入字节流
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/crates/aster_forge_xml.md` at line 168, 为安全检查示意图所在的 Markdown 代码块添加 text
语言标识,将无语言标识的围栏改为 ```text,并保持代码块内容不变。

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/aster_forge_xml/src/lib.rs`:
- Around line 256-279: Remove the unsafe pointer-based
descendants_mut/collect_mut_ptr implementation because it returns overlapping
mutable references to ancestors and descendants. Replace the API with a
non-aliasing design, preferably a mutable visitor such as visit_mut that invokes
the callback during traversal, or return paths/indices for later disjoint
access; update callers to use the new interface and preserve traversal coverage.
- Around line 8-14: 将 lib.rs 中的 serializer 模块声明从公开改为私有,保持与 parser 的模块封装方式一致;继续通过
pub use serializer::SerializeOptions 导出必要的配置类型,不要改变 Element::write、Display
或其他现有序列化入口。

In `@crates/aster_forge_xml/src/parser.rs`:
- Around line 126-201: Update parse() after the root element is built in the
Start and Empty branches to consume events through Eof before returning. Skip
comments, processing instructions, and whitespace-only text; return
Error::InvalidXml("extra content after root node".into()) for any additional
element or non-whitespace content, while preserving the existing root parsing
and error behavior.
- Around line 128-149: 在 build_tree 的 Event::Start 分支递归构造元素前,以及 parse() 的顶层
Event::Start 分支中,补充与 Event::Empty 分支一致的 check_element_count
调用;确保每个非自闭合元素(包括根元素)在创建前都计入 max_elements,并保留现有超限处理行为。

---

Nitpick comments:
In `@docs/crates/aster_forge_xml.md`:
- Line 168: 为安全检查示意图所在的 Markdown 代码块添加 text 语言标识,将无语言标识的围栏改为 ```text,并保持代码块内容不变。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7c1703cf-5611-457c-87c9-3626c6a2f9cf

📥 Commits

Reviewing files that changed from the base of the PR and between 88684df and 305ef17.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml
  • crates/aster_forge_xml/Cargo.toml
  • crates/aster_forge_xml/src/error.rs
  • crates/aster_forge_xml/src/lib.rs
  • crates/aster_forge_xml/src/parser.rs
  • crates/aster_forge_xml/src/serializer.rs
  • docs/crates/aster_forge_xml.md

Comment thread crates/aster_forge_xml/src/lib.rs Outdated
Comment thread crates/aster_forge_xml/src/lib.rs Outdated
Comment thread crates/aster_forge_xml/src/parser.rs Outdated
Comment thread crates/aster_forge_xml/src/parser.rs Outdated
…rser

Replace the lightweight `aster_forge_utils::xml` validation shim with a
full-featured, safety-bounded XML library in `aster_forge_xml`.

- Add `BorrowedDocument` / `XmlDocument` arena parser that keeps all
  plain values as zero-copy source slices and allocates only for
  decoded entities; supports `write_original` for byte-exact round-trips
- Add `XmlStreamReader` for namespace-resolved event streaming with
  `skip_current`, `capture_current`, and `read_text_current` helpers;
  enforces all safety limits incrementally without buffering the full input
- Add `XmlStreamWriter` with `XmlWriteOptions` for bounded, validated XML
  generation; rejects invalid names, duplicate attributes, forbidden
  namespace bindings, and unsafe character values at write time
- Expand `XmlSafetyPolicy` with granular limits: `max_input_bytes`,
  `max_elements`, `max_attributes_per_element`, `max_text_bytes`, and
  `max_events` in addition to existing `max_depth` and `reject_doctype`
- Redesign `Error` / `XmlSafetyError` hierarchy: `XmlSafetyError` is now
  `Copy + Eq`, carries `InvalidEncoding`, `OutputTooLarge`,
  `TooManyElements`, `TooManyAttributes`, and `TextTooLarge` variants, and
  is wrapped by `Error::Safety`; `Error::Io` carries the original
  `std::io::Error` rather than a string
- Remove `aster_forge_utils::xml` module and `quick-xml` dependency from
  `aster_forge_utils`; callers migrate to `aster_forge_xml` directly
- Add integration test suites: `xml`, `document`, `stream`, `writer`,
  `roxmltree_compat`, `xmltree_compat`, and a proptest property suite with
  a saved regression seed
- Add libfuzzer fuzz targets `parse_stream` and `writer_roundtrip`
- Add Criterion benchmarks for parse, write, and multistatus generation
  comparing `forge_arena`, `roxmltree`, `xmltree`, and `quick-xml`
- Register `aster_forge_xml` in docs sidebar, index, new-project guide,
  and README utilities table; remove the xml section from `aster_forge_utils` docs
@socket-security

socket-security Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​proptest@​1.11.09910093100100
Addedcargo/​xmltree@​0.12.010010093100100
Addedcargo/​roxmltree@​0.21.1100100100100100

View full report

@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

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

Actionable comments posted: 14

🧹 Nitpick comments (10)
crates/aster_forge_xml/benches/support/mod.rs (2)

150-215: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

两份一模一样的策略构造,抽个 helper。

L151-157 和 L199-205 完全重复;将来改一处忘另一处,两个 bench 就不再可比。另外这里放宽的 max_elements/max_events/max_text_bytesxml_bench.rs 中 DOM 路径使用的 XmlSafetyPolicy::untrusted() 默认值不同,跨路径对比时请注意这层不对称。

♻️ 建议抽取
+fn benchmark_policy(input: &[u8]) -> XmlSafetyPolicy {
+    XmlSafetyPolicy {
+        max_input_bytes: input.len().max(1),
+        max_elements: 1_000_000,
+        max_text_bytes: input.len().max(1),
+        max_events: 10_000_000,
+        ..XmlSafetyPolicy::untrusted()
+    }
+}
+
 pub(crate) fn walk_forge_stream(input: &[u8]) -> usize {
-    let policy = XmlSafetyPolicy {
-        max_input_bytes: input.len().max(1),
-        max_elements: 1_000_000,
-        max_text_bytes: input.len().max(1),
-        max_events: 10_000_000,
-        ..XmlSafetyPolicy::untrusted()
-    };
+    let policy = benchmark_policy(input);
     let mut reader = XmlStreamReader::new(input, policy).expect("benchmark policy is valid");

validate_forge_stream 同样替换。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/aster_forge_xml/benches/support/mod.rs` around lines 150 - 215,
Extract the duplicated XmlSafetyPolicy construction from walk_forge_stream and
validate_forge_stream into a shared helper, then have both functions obtain
their reader policy through that helper. Preserve the existing input-dependent
limits and relaxed max_elements/max_text_bytes/max_events values so both
benchmark paths remain comparable.

115-122: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

unescape 在新版 quick-xml 上是多余开销,会给对照组抹黑。

quick-xml 已把 BytesText::unescape 换成 decode,Text 事件不再包含转义片段,实体统一由 Event::GeneralRef 上报。这里 decode() 之后再 unescape() 属于纯多余扫描,还会把 fixture 里 "/< 的处理成本重复计入 quick-xml 对照路径——你在 PR 里贴的对比表就是靠这些数字支撑的。

♻️ 去掉多余的 unescape
             Event::Text(text) => {
-                let decoded = text.decode().expect("benchmark text is valid");
-                checksum = checksum.wrapping_add(
-                    unescape(&decoded)
-                        .expect("benchmark text entities are valid")
-                        .len(),
-                );
+                checksum = checksum
+                    .wrapping_add(text.decode().expect("benchmark text is valid").len());
             }

顺带移除顶部的 use quick_xml::escape::unescape;

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/aster_forge_xml/benches/support/mod.rs` around lines 115 - 122, 在基准测试的
Event::Text 分支中移除对 unescape 的调用,使 checksum 直接使用 text.decode() 的结果长度;同时删除顶部对
quick_xml::escape::unescape 的导入,保留现有有效性断言和其他事件处理逻辑不变。
crates/aster_forge_xml/benches/xml_memory.rs (3)

295-315: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

子进程失败时把 stderr 带上,不然只能靠占卜调试。

♻️ 建议改法
-            assert!(output.status.success(), "memory benchmark child failed");
+            assert!(
+                output.status.success(),
+                "memory benchmark child failed: mode={mode} fixture={fixture_name}\n{}",
+                String::from_utf8_lossy(&output.stderr)
+            );

两处 assert! 都建议这么改。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/aster_forge_xml/benches/xml_memory.rs` around lines 295 - 315, Update
both child-process success assertions in the benchmark loops to include the
captured output.stderr when the command fails, while preserving the existing
success check and stdout printing behavior.

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

i64_to_u64 只在 unix cfg 下用到,Windows 上就是个未使用导入。

你自己的跑分报告写的是 Windows 10 —— 那条路走 #[cfg(not(any(target_os = "linux", target_os = "macos")))] 分支,L10 的导入没人用。CI 只要带 -D warnings,非 unix 目标立刻炸。给导入加上同样的 cfg 或把它挪进函数体内。

♻️ 建议改法
-use aster_forge_utils::numbers::i64_to_u64;
 use aster_forge_xml::{BorrowedDocument, ValidatedXml, XmlSafetyPolicy, validate_xml_input};
#[cfg(any(target_os = "linux", target_os = "macos"))]
fn peak_rss_bytes() -> u64 {
    use aster_forge_utils::numbers::i64_to_u64;
    // ...
}

Also applies to: 238-263

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/aster_forge_xml/benches/xml_memory.rs` at line 10, Update the
i64_to_u64 import used by peak_rss_bytes to be available only on Linux and
macOS, either by applying the matching cfg attribute or moving the import inside
that cfg-gated function; keep the non-Unix implementation free of unused
imports.

110-212: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

15 个 arm、15 次 print_result,复制粘贴的味道太冲。

除了 forge_arena_original / xmltree_write 需要重置测量窗口,其余 arm 的结构完全一致。建议让 match 只负责"跑负载并返回 snapshot",print_result 在函数末尾调用一次;漏写一次打印的机会也就没了。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/aster_forge_xml/benches/xml_memory.rs` around lines 110 - 212, 重构
run_child,使 match 各分支仅执行对应负载并返回测量结果快照,由函数末尾统一调用一次 print_result。保留
forge_arena_original 和 xmltree_write 在写出阶段重置测量窗口的特殊行为,并确保所有分支仍传递相同的
mode、fixture_name 和 input.len() 信息。
crates/aster_forge_xml/fuzz/Cargo.toml (1)

10-29: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

给 fuzz crate 加一个独立编译任务。

libfuzzer-sys 0.4.13 存在;但这个 [workspace] members = ["."] 的 fuzz crate 不会随父 workspace 一起构建,API 一变就会默默掉队。CI 加一句 cargo build --manifest-path crates/aster_forge_xml/fuzz/Cargo.tomlcargo fuzz build

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/aster_forge_xml/fuzz/Cargo.toml` around lines 10 - 29, 为 fuzz crate
增加独立的 CI 编译任务,确保包含 parse_stream 和 writer_roundtrip 的清单能被实际构建。使用
crates/aster_forge_xml/fuzz/Cargo.toml 对应的 cargo build --manifest-path,或等价的
cargo fuzz build,并将其纳入现有 CI 流程。
crates/aster_forge_xml/src/error.rs (1)

65-84: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Safety 的 Display 转发 + source() 同时返回自己,错误链会把同一句话说两遍。

L68 error.fmt(f) 已经把 XmlSafetyError 的文本原样吐出来了,L79 又把它作为 source() 暴露。任何按惯例遍历错误链输出的地方(anyhowtracingerror.source() 链、{:#})都会打印成 XML nesting depth exceeds the configured limit: XML nesting depth exceeds the configured limit。错误链的约定是 source 提供新增信息,转发型 Display 就不该再挂 source。

Io 那条有 XML I/O error: 前缀,重复度低一些,但同样是重复内容,看你要不要一起收。

♻️ 建议改动
 impl std::error::Error for Error {
     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
         match self {
-            Self::Safety(error) => Some(error),
             Self::Io(error) => Some(error),
-            Self::InvalidXml(_) | Self::InvalidData(_) => None,
+            Self::Safety(_) | Self::InvalidXml(_) | Self::InvalidData(_) => None,
         }
     }
 }

如果坚持要保留 Safety 的 source(比如下游想 downcast_ref::<XmlSafetyError>()),那就把 L68 改成带前缀的写法,别让两层文本一模一样。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/aster_forge_xml/src/error.rs` around lines 65 - 84, Update the Error
implementations for the Safety variant so its Display output and source chain do
not produce identical text: either stop exposing Safety through source(), or add
a distinct contextual prefix in fmt::Display while preserving downcasting. Apply
the same consistency decision to Io if needed, keeping InvalidXml and
InvalidData behavior unchanged.
crates/aster_forge_xml/src/document.rs (3)

992-1018: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

resolve_namespace + builder_value 是 L263-279 / L246-254 的逐行复制,只为了 VecBox<[]> 的差别。

两对函数的算法完全一致,唯一区别是 builder 阶段访问 Vec<NamespaceScope> / Vec<Box<str>>,document 阶段访问 Box<[NamespaceScope]> / Box<[Box<str>]>——而 Vec<T>Box<[T]>Deref<Target = [T]>,这个"差别"根本不需要两份代码。

把 arena 四件套抽成一个私有结构体(持有 &[ArenaNode] / &[NamespaceScope] / &[NamespaceBinding] / &[Box<str>] 的视图),让 builder 和 XmlDocument 都借它做查询,四个函数变两个。现在两份一致,改动便宜;等哪天只改了一边,build_element 的前缀校验和 ElementRef::namespace() 就会对同一棵树给出不同答案。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/aster_forge_xml/src/document.rs` around lines 992 - 1018, Extract the
duplicated namespace lookup and value-resolution logic from resolve_namespace
and builder_value into one private arena-view structure holding slices of
namespace scopes, bindings, and owned values. Make both the builder and
XmlDocument pass their Vec or boxed-slice storage through this shared structure,
relying on slice deref compatibility, and replace the four existing helper
implementations with the shared two methods while preserving current lookup
order and XML namespace handling.

246-254: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

stored_index 把"内部状态坏了"翻译成"索引越界 panic",而同一个函数里 UTF-8 失败又静默返回空串。同一份不变量,两种完全相反的失败模式。

stored_index 的注释坦白了设计意图:"make malformed internal state fail indexing"——也就是转换失败时返回 usize::MAX,让后续的 self.owned_values[usize::MAX] 直接炸。而 L253 的 from_utf8(...).unwrap_or("") 遇到同一类不变量破坏却选择静默吐空串,上层拿到的是"这个元素没名字"而不是任何错误。

另外 L251 let end = start + stored_index(value.length, ...) 是裸加法:length 一旦是 usize::MAX,debug 下 overflow panic,release 下 wrap 成小数字,接着 &source[start..end]start > end panic。三条路径三种炸法。

这些 ValueRef 目前全由本 crate 的 builder 构造、字段私有、外部无法伪造,所以当前不可达——我不是在说它今天会炸。我是在说 crate 顶上写着 deny(clippy::panic)lib.rs L12),转手就把 panic 当成内部错误处理机制,而且还只用了一半。要么统一成"内部不变量违反 → 返回 Error/空值并且有 debug_assert",要么统一成"直接 panic 且注释说明这是不可达",别一半一半。resolve_namespace(L268、L270)和 AttributeRef::data(L573)也是同一套裸索引。

Also applies to: 1094-1098

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/aster_forge_xml/src/document.rs` around lines 246 - 254, 统一 ValueRef
内部状态异常的处理方式,重点更新 Document::value,并同步检查 resolve_namespace 与 AttributeRef::data
的裸索引和范围计算。避免 stored_index、UTF-8 转换及 start + length 分别产生
panic、静默空串和溢出;在现有返回类型约束下采用一致的安全失败结果,并用 debug_assert 标记不可达的不变量违规,确保无效范围不会继续切片或索引。

658-658: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

document.rs 的闭标签校验依赖 quick-xml 默认配置,不如直接写在代码里。

check_end_names 默认是开着的,但 DocumentBuilder 在只配置 trim_text(false) 的情况下就让 Event::End(_) => self.end_element(event_end) 直接丢了 end_name;要修改开关或升级 quick-xml 语义时,这里跟 parser.rs 自带 qualified_name 比对的行为就只剩一个入口。要么显式设置 reader.config_mut().check_end_names = true,要么像 parser.rs 那样自己比对闭标签名,别靠库默认值维持这条结构校验。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/aster_forge_xml/src/document.rs` at line 658, 在 DocumentBuilder 的
quick-xml reader 配置处显式启用闭标签名称校验,避免依赖默认配置;确保 Event::End 经过 end_element(event_end)
时仍保留结构校验行为,并与 parser.rs 的 qualified_name 比对逻辑保持一致。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/aster_forge_xml/benches/support/mod.rs`:
- Around line 301-350: 统一处理 xmltree 对照 benchmark:优先将
crates/aster_forge_xml/benches/support/mod.rs#L301-L350 的
write_xmltree_multistatus、dav_element、xmltree_text_element 及依赖迁移到不属于默认 workspace
的独立 bench crate,并同步移除 manifest 与 lockfile 中的 xmltree;同时处理
crates/aster_forge_xml/benches/xml_bench.rs#L46-L66 的
xmltree_owned、validate_plus_xmltree,以及
crates/aster_forge_xml/benches/xml_memory.rs#L172-L187 的 xmltree_write、相关模式和
mode 列表。若不迁移,则必须在文档中明确记录仅 benchmark 保留 xmltree 的例外。

In `@crates/aster_forge_xml/benches/xml_bench.rs`:
- Around line 23-26: 统一 xml_bench.rs 与 xml_memory.rs 对 multistatus_10000 的
fixture 选择,避免一个 benchmark 过滤而另一个仍使用它;在 fixtures() 或两者共享的筛选逻辑处明确说明排除原因(默认
untrusted 上限或跑分耗时),并尽量让被排除的约 2.4 MB 字符串不再生成。

In `@crates/aster_forge_xml/benches/xml_memory.rs`:
- Around line 281-294: 统一 CPU 与内存 benchmark 对 multistatus_10000 的
XmlSafetyPolicy 口径:先核对默认 max_input_bytes/max_elements 及 XmlStreamWriter::new
的输出上限;若默认上限不足,则在 crates/aster_forge_xml/benches/xml_memory.rs#L281-L294
的相关模式传入放宽策略、在 crates/aster_forge_xml/benches/support/mod.rs#L217-L221 为
XmlStreamWriter 显式使用该策略,并在 crates/aster_forge_xml/benches/xml_bench.rs#L23-L26
保留过滤并补充原因注释;若上限足够,则移除该过滤并确保内存 benchmark 可稳定运行。

In `@crates/aster_forge_xml/Cargo.toml`:
- Around line 15-20: Remove the xmltree dependency from the [dev-dependencies]
section of the crate manifest, and eliminate any remaining xmltree references
from tests, benchmarks, and related configuration so Cargo.lock no longer
retains the package. Also inspect roxmltree usage and remove it if it is only
used for compatibility comparisons, preserving only dependencies required by
active tests or benchmarks.

In `@crates/aster_forge_xml/src/document.rs`:
- Around line 784-814: 在处理 start.attributes() 的循环中,使用现有的 validate_qualified_name
校验每个属性名,包括 xmlns 和 xmlns:* 声明;在根据 name 判断命名空间绑定之前完成校验,使非法前缀(如 1x)返回 Malformed,并与
parser.rs 的第一遍校验保持一致。
- Around line 445-447: Update the iteration logic in DescendantElements::next
and the corresponding traversal path around the second reported occurrence to
avoid collecting child_elements into a temporary Vec. Record the existing stack
length, extend self.stack directly with the child iterator, then reverse only
the newly appended slice in place so child order is preserved without an
allocation per visited node.
- Around line 903-935: The text_node function accumulates text_bytes after
trimming the value when trim_whitespace is true, but validate_xml_input counts
bytes before trimming. This causes inconsistent safety limit enforcement between
the two validation paths. Move the text_bytes accumulation (the checked_add call
and max_text_bytes comparison) to occur before the trim_whitespace conditional
block so that the byte limit is applied to the original input length rather than
the post-trim length, ensuring both code paths enforce the safety limit
consistently on raw input.

In `@crates/aster_forge_xml/src/parser.rs`:
- Around line 143-148: 统一 quick_xml 错误到 XmlSafetyError 的映射逻辑:将 document.rs 中的
map_quick_xml_error 提取到 crate 内共享位置,并让 validate_xml_input 的 read_event
错误路径复用该函数,而不是一律转换为 Error::InvalidXml。保留 safety_error 对已映射错误的处理,使非法编码输入在验证和 DOM
解析两个公共入口都返回 InvalidEncoding。
- Around line 400-463: Consolidate the duplicated XML safety helpers into one
new private module: in crates/aster_forge_xml/src/parser.rs lines 400-463,
remove the local implementations and import utf8, validate_qualified_name,
valid_name, validate_namespace_binding, and both namespace URI constants; in
crates/aster_forge_xml/src/document.rs lines 1021-1088, remove the duplicate
implementations and import the same shared symbols, moving document.rs’s
split_qualified_name into that module so validate_qualified_name reuses it. Also
move map_quick_xml_error into the shared module and use it at parser.rs lines
241-243. The four already-divergent behaviors require separate fixes and are not
addressed by this consolidation.

In `@crates/aster_forge_xml/src/stream.rs`:
- Around line 549-554: 更新 stream.rs 中处理 XmlStreamEvent::Comment 的分支,将
BytesText::new 替换为 BytesText::from_escaped,确保已解码的注释内容不会被二次转义,并保持原始 XML 注释内容不变。

In `@crates/aster_forge_xml/src/writer.rs`:
- Around line 433-451: Update attributes_share_expanded_name so duplicate
namespace declaration attributes are treated as conflicting: identical
declarations such as xmlns:a and xmlns:a, including duplicate default xmlns,
must return true regardless of their values. Preserve the existing expanded-name
comparison for non-declaration attributes. Extend the duplicate-attribute tests
in writer.rs to cover both prefixed and default namespace declarations.
- Around line 244-271: Update validated_subtree to prevent raw unprefixed
elements from being reinterpreted under the caller’s non-empty default
namespace. Before write_raw, detect whether the embedded subtree contains
unprefixed elements and whether the current writer scope has a non-empty default
namespace, then reject the operation with the appropriate invalid-data error (or
otherwise explicitly reset the namespace with xmlns=""); preserve the existing
depth and attribute validation.

In `@crates/aster_forge_xml/tests/writer.rs`:
- Line 45: 将 writer 测试中通过 xmltree::Element::parse 进行的输出校验移入
tests/xmltree_compat.rs 的 round-trip/parse contract 测试;更新 writer 测试以移除该校验及对
xmltree 的依赖,确保 xmltree 仅保留在兼容性测试中。

In `@docs/crates/aster_forge_xml.md`:
- Line 217: 将 benchmark 记录中的日期从 `2026-07-25` 更新为实际采样日期;若这些结果确实采集于 2026 年 7 月 24
日,则改为 `2026-07-24`,并同步 PR 说明中的报告日期,保持其余 workload-specific benchmark 数据不变。

---

Nitpick comments:
In `@crates/aster_forge_xml/benches/support/mod.rs`:
- Around line 150-215: Extract the duplicated XmlSafetyPolicy construction from
walk_forge_stream and validate_forge_stream into a shared helper, then have both
functions obtain their reader policy through that helper. Preserve the existing
input-dependent limits and relaxed max_elements/max_text_bytes/max_events values
so both benchmark paths remain comparable.
- Around line 115-122: 在基准测试的 Event::Text 分支中移除对 unescape 的调用,使 checksum 直接使用
text.decode() 的结果长度;同时删除顶部对 quick_xml::escape::unescape
的导入,保留现有有效性断言和其他事件处理逻辑不变。

In `@crates/aster_forge_xml/benches/xml_memory.rs`:
- Around line 295-315: Update both child-process success assertions in the
benchmark loops to include the captured output.stderr when the command fails,
while preserving the existing success check and stdout printing behavior.
- Line 10: Update the i64_to_u64 import used by peak_rss_bytes to be available
only on Linux and macOS, either by applying the matching cfg attribute or moving
the import inside that cfg-gated function; keep the non-Unix implementation free
of unused imports.
- Around line 110-212: 重构 run_child,使 match 各分支仅执行对应负载并返回测量结果快照,由函数末尾统一调用一次
print_result。保留 forge_arena_original 和 xmltree_write
在写出阶段重置测量窗口的特殊行为,并确保所有分支仍传递相同的 mode、fixture_name 和 input.len() 信息。

In `@crates/aster_forge_xml/fuzz/Cargo.toml`:
- Around line 10-29: 为 fuzz crate 增加独立的 CI 编译任务,确保包含 parse_stream 和
writer_roundtrip 的清单能被实际构建。使用 crates/aster_forge_xml/fuzz/Cargo.toml 对应的 cargo
build --manifest-path,或等价的 cargo fuzz build,并将其纳入现有 CI 流程。

In `@crates/aster_forge_xml/src/document.rs`:
- Around line 992-1018: Extract the duplicated namespace lookup and
value-resolution logic from resolve_namespace and builder_value into one private
arena-view structure holding slices of namespace scopes, bindings, and owned
values. Make both the builder and XmlDocument pass their Vec or boxed-slice
storage through this shared structure, relying on slice deref compatibility, and
replace the four existing helper implementations with the shared two methods
while preserving current lookup order and XML namespace handling.
- Around line 246-254: 统一 ValueRef 内部状态异常的处理方式,重点更新 Document::value,并同步检查
resolve_namespace 与 AttributeRef::data 的裸索引和范围计算。避免 stored_index、UTF-8 转换及 start
+ length 分别产生 panic、静默空串和溢出;在现有返回类型约束下采用一致的安全失败结果,并用 debug_assert
标记不可达的不变量违规,确保无效范围不会继续切片或索引。
- Line 658: 在 DocumentBuilder 的 quick-xml reader 配置处显式启用闭标签名称校验,避免依赖默认配置;确保
Event::End 经过 end_element(event_end) 时仍保留结构校验行为,并与 parser.rs 的 qualified_name
比对逻辑保持一致。

In `@crates/aster_forge_xml/src/error.rs`:
- Around line 65-84: Update the Error implementations for the Safety variant so
its Display output and source chain do not produce identical text: either stop
exposing Safety through source(), or add a distinct contextual prefix in
fmt::Display while preserving downcasting. Apply the same consistency decision
to Io if needed, keeping InvalidXml and InvalidData behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 43366832-dfa8-42ae-a4b9-1533a173f1fb

📥 Commits

Reviewing files that changed from the base of the PR and between 305ef17 and 5e83eb4.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (31)
  • README.md
  • crates/aster_forge_utils/Cargo.toml
  • crates/aster_forge_utils/src/lib.rs
  • crates/aster_forge_utils/src/xml.rs
  • crates/aster_forge_xml/Cargo.toml
  • crates/aster_forge_xml/benches/support/mod.rs
  • crates/aster_forge_xml/benches/xml_bench.rs
  • crates/aster_forge_xml/benches/xml_memory.rs
  • crates/aster_forge_xml/fuzz/.gitignore
  • crates/aster_forge_xml/fuzz/Cargo.toml
  • crates/aster_forge_xml/fuzz/fuzz_targets/parse_stream.rs
  • crates/aster_forge_xml/fuzz/fuzz_targets/writer_roundtrip.rs
  • crates/aster_forge_xml/src/document.rs
  • crates/aster_forge_xml/src/error.rs
  • crates/aster_forge_xml/src/lib.rs
  • crates/aster_forge_xml/src/parser.rs
  • crates/aster_forge_xml/src/stream.rs
  • crates/aster_forge_xml/src/writer.rs
  • crates/aster_forge_xml/tests/document.rs
  • crates/aster_forge_xml/tests/property.proptest-regressions
  • crates/aster_forge_xml/tests/property.rs
  • crates/aster_forge_xml/tests/roxmltree_compat.rs
  • crates/aster_forge_xml/tests/stream.rs
  • crates/aster_forge_xml/tests/writer.rs
  • crates/aster_forge_xml/tests/xml.rs
  • crates/aster_forge_xml/tests/xmltree_compat.rs
  • docs/.vitepress/config.ts
  • docs/crates/aster_forge_utils.md
  • docs/crates/aster_forge_xml.md
  • docs/guide/new-project-integration.md
  • docs/index.md
💤 Files with no reviewable changes (3)
  • crates/aster_forge_utils/Cargo.toml
  • crates/aster_forge_utils/src/lib.rs
  • crates/aster_forge_utils/src/xml.rs

Comment thread crates/aster_forge_xml/benches/support/mod.rs
Comment thread crates/aster_forge_xml/benches/xml_bench.rs Outdated
Comment thread crates/aster_forge_xml/benches/xml_memory.rs
Comment thread crates/aster_forge_xml/Cargo.toml
Comment thread crates/aster_forge_xml/src/document.rs
Comment thread crates/aster_forge_xml/src/stream.rs
Comment thread crates/aster_forge_xml/src/writer.rs
Comment thread crates/aster_forge_xml/src/writer.rs
Comment thread crates/aster_forge_xml/tests/writer.rs
Comment thread docs/crates/aster_forge_xml.md
feat(aster_forge_xml): extract syntax validation module and improve parser robustness

**Core improvements:**
- Extract shared XML syntax validation functions into new `syntax` module (utf8, validate_qualified_name, split_qualified_name, validate_namespace_binding, map_quick_xml_error)
- Add `ArenaView` abstraction for safe internal value and namespace resolution with bounds checking
- Enable `check_end_names` in quick-xml reader configuration for stricter tag matching
- Validate qualified names during attribute parsing in arena builder
- Count text bytes before trimming to enforce limits on original input size

**Memory benchmark refinements:**
- Split benchmark fixtures into `cpu_fixtures()` and `memory_fixtures()` to avoid inflating multi-sample benchmark setup with large 10k-response documents
- Improve child process error reporting with stderr output on failure
- Factor out common `stream_policy()` helper for benchmark reader configuration

**Robustness and correctness:**
- Add bounds checking to `AttributeRef::data()` and namespace resolution paths
- Fix `DescendantElements` iterator to avoid intermediate allocation
- Preserve comment escaping in stream capture using `BytesText::from_escaped`
- Reject validated subtrees with unprefixed elements when writer has default namespace
- Fix duplicate attribute detection to handle xmlns declarations correctly
- Add error display test coverage and improve `Error::Safety` formatting

**Testing:**
- Add test for descendant iteration document order
- Add test for arena value bounds checking
- Add test for invalid encoding classification consistency
- Add test for trim whitespace byte limit enforcement
- Add test for validated subtree namespace inheritance

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/rust.yml:
- Line 9: Update the Rust workflow’s paths configuration to include the fuzz
crate’s source directory and harness files, including
crates/aster_forge_xml/fuzz/fuzz_targets/*.rs, alongside its Cargo.toml entry so
harness changes trigger CI.
- Around line 53-54: Update the “Build XML fuzz harness” workflow step to build
with the nightly Rust toolchain, installing or selecting nightly as needed, and
invoke the existing Cargo manifest build through cargo +nightly so libFuzzer
sanitizer flags are supported.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 644c51c3-fbd5-4975-8e36-fe470989556c

📥 Commits

Reviewing files that changed from the base of the PR and between 5e83eb4 and 59648d4.

📒 Files selected for processing (15)
  • .github/workflows/rust.yml
  • crates/aster_forge_xml/benches/support/mod.rs
  • crates/aster_forge_xml/benches/xml_bench.rs
  • crates/aster_forge_xml/benches/xml_memory.rs
  • crates/aster_forge_xml/src/document.rs
  • crates/aster_forge_xml/src/error.rs
  • crates/aster_forge_xml/src/lib.rs
  • crates/aster_forge_xml/src/parser.rs
  • crates/aster_forge_xml/src/stream.rs
  • crates/aster_forge_xml/src/syntax.rs
  • crates/aster_forge_xml/src/writer.rs
  • crates/aster_forge_xml/tests/document.rs
  • crates/aster_forge_xml/tests/stream.rs
  • crates/aster_forge_xml/tests/writer.rs
  • crates/aster_forge_xml/tests/xml.rs
🚧 Files skipped from review as they are similar to previous changes (10)
  • crates/aster_forge_xml/benches/xml_bench.rs
  • crates/aster_forge_xml/benches/xml_memory.rs
  • crates/aster_forge_xml/src/error.rs
  • crates/aster_forge_xml/tests/stream.rs
  • crates/aster_forge_xml/tests/writer.rs
  • crates/aster_forge_xml/tests/xml.rs
  • crates/aster_forge_xml/src/parser.rs
  • crates/aster_forge_xml/src/stream.rs
  • crates/aster_forge_xml/src/document.rs
  • crates/aster_forge_xml/src/writer.rs

- '**/*.rs'
- 'Cargo.toml'
- 'Cargo.lock'
- 'crates/aster_forge_xml/fuzz/Cargo.toml'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

rg -n -C3 'paths:|aster_forge_xml|fuzz_targets' .github/workflows/rust.yml

Repository: AsterCommunity/AsterForge

Length of output: 988


别把 fuzz harness 源码变更漏网。

当前 paths 只覆盖 crates/aster_forge_xml/fuzz/Cargo.toml;像 crates/aster_forge_xml/fuzz/fuzz_targets/*.rs 这样的 harness 源码修改不会触发 CI。把 fuzz crate 的源文件/目录一起纳入 paths

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/rust.yml at line 9, Update the Rust workflow’s paths
configuration to include the fuzz crate’s source directory and harness files,
including crates/aster_forge_xml/fuzz/fuzz_targets/*.rs, alongside its
Cargo.toml entry so harness changes trigger CI.

Comment thread .github/workflows/rust.yml Outdated
- Install nightly Rust toolchain with minimal profile before fuzzing
- Use `cargo +nightly` to build XML fuzz harness explicitly on nightly
- Ensures fuzz targets compile with required nightly features
@AptS-1547 AptS-1547 self-assigned this Jul 24, 2026
@AptS-1547 AptS-1547 added documentation Improvements or additions to documentation enhancement New feature or request good first issue Good for newcomers labels Jul 24, 2026

@AptS-1547 AptS-1547 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@AptS-1547
AptS-1547 merged commit 83462f2 into AsterCommunity:master Jul 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request good first issue Good for newcomers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor]: remove xmltree from the AsterDrive XML stack

2 participants