Skip to content

feat(xmlsec1)!: own document tree for the libxmlsec1 surface, no libxml2 - #454

Merged
polaz merged 1 commit into
mainfrom
feat/#451-owned-tree
Nov 11, 2026
Merged

polaz merged 1 commit into
mainfrom
feat/#451-owned-tree

Conversation

@polaz

@polaz polaz commented Nov 11, 2026

Copy link
Copy Markdown
Member

Summary

  • The libxmlsec1-compatible library (xml-sec-xmlsec1) and the tree library (xml-sec-libxml2) link, load and call no C library besides the platform's C runtime: a program uses libxmlsec1's interfaces without libxml2.
  • Documents are the core's own trees behind opaque handles, validated on every use and never dereferenced, read and changed through our own tree functions shaped like libxml2's (xs prefix where libxml2 has xml).
  • No function reads a file, a URL or an external entity itself; the program passes the bytes.

Changes

  • Core: OwnedTree (feature owned-tree, which leaves the parser backend a build selects alone), a Rust-owned mutable document over the xmloxide arena, parsed from text or from bytes in the encoding they select, under the policy with its limits enforced while parsing, implementing the external-tree contract; XmlDocument::from_owned_tree / into_owned_tree lend it to an operation and snapshot_of_external_tree reads it without taking it, as a read-only document; the tree's ID table ties each ID to the attribute carrying it (xml:id and caller-registered IDs), keeps IDs unique among live elements and follows attribute edits.
  • xml-sec-libxml2: the handle table (documents, nodes, attributes, namespace declarations, XPath namespace nodes, node sets) with values from a counter that never repeats and a lock per document; the xs* tree functions and include/xs_tree.h with incomplete xmlDoc/xmlNode/xmlNs/xmlAttr/xmlNodeSet types; output and input buffers over the caller's callbacks or memory; the heap released with xsFree; xsSetGenericErrorFunc; xs_tree_document, a clean C API document over a tree document that reads and edits the tree at every operation, so the caller may change it between calls.
  • xml-sec-xmlsec1: every tree access goes through those handles; node sets, buffers and parsing are the library's own; read-only transforms (C14N, the XPath family, the relationship transform) read a snapshot, so C callbacks still see the live tree; error reports go through the generic error channel.
  • Headers: libxmlsec1's own, with xs_tree.h in place of libxml2's headers and the functions that read a file or install an entity loader left out (xmlSecParseFile, xmlSecBufferReadFile, xmlSecParsePrepareCtxt, xmlSecSetExternalEntityLoader); xmlsec1-headers writes and checks them against the oracle.
  • The libxml2 symbol table, the projection of a caller's libxml2 tree, its struct layouts and the test loader are removed; CI no longer provisions libxml2 for these crates.

Testing

The C test programs use the tree functions: capi --xmlsec1 builds each once against the libxmlsec1 1.3.13 oracle, with its tree calls mapped onto libxml2, and once against the library, and both print the same; capi runs the clean C API and tree-document round trips linking nothing else, on Linux, macOS and Windows. Tests, lints, formatting, the header check and the feature contract pass.

Replaces #453.

BREAKING CHANGE: xs_libxml2_document is replaced by xs_tree_document over a tree document of xs_tree.h; xmlSecParseFile, xmlSecBufferReadFile, xmlSecParsePrepareCtxt and xmlSecSetExternalEntityLoader are not offered.

Part of #451

The libxmlsec1-compatible library and the tree library link, load and
call no C library besides the platform's C runtime. Documents are the
core's trees behind opaque handles, read and changed through our own
tree functions shaped like libxml2's.

- core: OwnedTree (feature owned-tree, which compiles the xmloxide arena
  for the tree without making xmloxide a parser backend), a Rust-owned
  mutable document parsed from text or from bytes in the encoding they
  select, under the policy with its limits enforced while parsing and a
  DOCTYPE the policy forbids refused before its subset is read; it
  implements the external-tree contract; XmlDocument lends it to an
  operation (from_owned_tree, into_owned_tree) or reads a read-only
  snapshot of it (snapshot_of_external_tree); its ID table ties each ID
  to the attribute carrying it, holds normalized xml:id values and the
  IDs a caller registers, keeps them unique among live elements and
  follows attribute edits
- xml-sec-libxml2: the handle table (documents, nodes, attributes,
  namespace declarations and XPath namespace nodes, node sets) with
  handles and document slots from a counter that never repeats,
  validated on every use, and a lock per document; the xs* tree
  functions and xs_tree.h with incomplete types; output and input
  buffers over the caller's callbacks or memory; the heap released with
  xsFree; a per-thread generic error channel; xs_tree_document, a clean
  C API document over a tree document that reads the tree at every
  operation
- xml-sec-xmlsec1: every tree access goes through the handles; node
  sets, buffers and parsing are the library's own; read-only transforms
  read a snapshot so C callbacks still see the live tree; the headers
  are libxmlsec1's with xs_tree.h in place of libxml2's, generated and
  checked by xmlsec1-headers, and leave out the functions that read a
  file or install an entity loader
- the C test programs use the tree functions; capi --xmlsec1 builds each
  against the libxmlsec1 oracle with the tree calls mapped onto libxml2
  and against the library, and both print the same; the library's own
  round trips link nothing else, on every platform

BREAKING CHANGE: xs_libxml2_document is replaced by xs_tree_document over
a tree document of xs_tree.h; xmlSecParseFile, xmlSecBufferReadFile,
xmlSecParsePrepareCtxt and xmlSecSetExternalEntityLoader are not offered.

Part of #451
@coderabbitai

coderabbitai Bot commented Nov 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 104 files, which is 4 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 0a64d6e and aab8628.

Files selected for processing: 104

  • .github/workflows/ci.yml
  • Cargo.toml
  • crates/xml-sec-libxml2/Cargo.toml
  • crates/xml-sec-libxml2/SAFETY.md
  • crates/xml-sec-libxml2/include/xml_sec_libxml2.h
  • crates/xml-sec-libxml2/include/xs_tree.h
  • crates/xml-sec-libxml2/src/document.rs
  • crates/xml-sec-libxml2/src/document/tests.rs
  • crates/xml-sec-libxml2/src/ffi.rs
  • crates/xml-sec-libxml2/src/ffi/errors.rs
  • crates/xml-sec-libxml2/src/ffi/errors/tests.rs
  • crates/xml-sec-libxml2/src/ffi/io.rs
  • crates/xml-sec-libxml2/src/ffi/io/tests.rs
  • crates/xml-sec-libxml2/src/ffi/libxml2.rs
  • crates/xml-sec-libxml2/src/ffi/memory.rs
  • crates/xml-sec-libxml2/src/ffi/testing.rs
  • crates/xml-sec-libxml2/src/ffi/tests.rs
  • crates/xml-sec-libxml2/src/ffi/tree.rs
  • crates/xml-sec-libxml2/src/ffi/tree/tests.rs
  • crates/xml-sec-libxml2/src/handles.rs
  • crates/xml-sec-libxml2/src/handles/tests.rs
  • crates/xml-sec-libxml2/src/lib.rs
  • crates/xml-sec-libxml2/src/nodes.rs
  • crates/xml-sec-libxml2/src/policy.rs
  • crates/xml-sec-libxml2/src/slot_tree.rs
  • crates/xml-sec-libxml2/tests/c/roundtrip.c
  • crates/xml-sec-libxml2/tests/layout.c
  • crates/xml-sec-xmlsec1/Cargo.toml
  • crates/xml-sec-xmlsec1/SAFETY.md
  • crates/xml-sec-xmlsec1/include/xmlsec/app.h
  • crates/xml-sec-xmlsec1/include/xmlsec/base64.h
  • crates/xml-sec-xmlsec1/include/xmlsec/bn.h
  • crates/xml-sec-xmlsec1/include/xmlsec/buffer.h
  • crates/xml-sec-xmlsec1/include/xmlsec/dl.h
  • crates/xml-sec-xmlsec1/include/xmlsec/io.h
  • crates/xml-sec-xmlsec1/include/xmlsec/keyinfo.h
  • crates/xml-sec-xmlsec1/include/xmlsec/keysdata.h
  • crates/xml-sec-xmlsec1/include/xmlsec/membuf.h
  • crates/xml-sec-xmlsec1/include/xmlsec/nodeset.h
  • crates/xml-sec-xmlsec1/include/xmlsec/parser.h
  • crates/xml-sec-xmlsec1/include/xmlsec/private.h
  • crates/xml-sec-xmlsec1/include/xmlsec/strings.h
  • crates/xml-sec-xmlsec1/include/xmlsec/templates.h
  • crates/xml-sec-xmlsec1/include/xmlsec/transforms.h
  • crates/xml-sec-xmlsec1/include/xmlsec/xmldsig.h
  • crates/xml-sec-xmlsec1/include/xmlsec/xmlenc.h
  • crates/xml-sec-xmlsec1/include/xmlsec/xmlsec.h
  • crates/xml-sec-xmlsec1/include/xmlsec/xmltree.h
  • crates/xml-sec-xmlsec1/src/ffi.rs
  • crates/xml-sec-xmlsec1/src/ffi/buffer.rs
  • crates/xml-sec-xmlsec1/src/ffi/buffer/tests.rs
  • crates/xml-sec-xmlsec1/src/ffi/errors.rs
  • crates/xml-sec-xmlsec1/src/ffi/library.rs
  • crates/xml-sec-xmlsec1/src/ffi/nodeset.rs
  • crates/xml-sec-xmlsec1/src/ffi/nodeset/tests.rs
  • crates/xml-sec-xmlsec1/src/ffi/parser.rs
  • crates/xml-sec-xmlsec1/src/ffi/parser/tests.rs
  • crates/xml-sec-xmlsec1/src/ffi/policy.rs
  • crates/xml-sec-xmlsec1/src/ffi/tests.rs
  • crates/xml-sec-xmlsec1/src/ffi/transforms.rs
  • crates/xml-sec-xmlsec1/src/ffi/transforms/builtin.rs
  • crates/xml-sec-xmlsec1/src/ffi/transforms/ctx.rs
  • crates/xml-sec-xmlsec1/src/ffi/transforms/io.rs
  • crates/xml-sec-xmlsec1/src/ffi/transforms/parser.rs
  • crates/xml-sec-xmlsec1/src/ffi/transforms/relationship.rs
  • crates/xml-sec-xmlsec1/src/ffi/transforms/tests.rs
  • crates/xml-sec-xmlsec1/src/ffi/transforms/xpath.rs
  • crates/xml-sec-xmlsec1/src/ffi/transforms/xpath/tests.rs
  • crates/xml-sec-xmlsec1/src/ffi/tree.rs
  • crates/xml-sec-xmlsec1/src/ffi/xmltree.rs
  • crates/xml-sec-xmlsec1/src/lib.rs
  • crates/xml-sec-xmlsec1/tests/c/base64.c
  • crates/xml-sec-xmlsec1/tests/c/core.c
  • crates/xml-sec-xmlsec1/tests/c/errors.c
  • crates/xml-sec-xmlsec1/tests/c/io.c
  • crates/xml-sec-xmlsec1/tests/c/keysdata.c
  • crates/xml-sec-xmlsec1/tests/c/library.c
  • crates/xml-sec-xmlsec1/tests/c/nodeset.c
  • crates/xml-sec-xmlsec1/tests/c/parser.c
  • crates/xml-sec-xmlsec1/tests/c/transforms.c
  • crates/xml-sec-xmlsec1/tests/c/tree.h
  • crates/xml-sec-xmlsec1/tests/c/xpath.c
  • crates/xml-sec-xmlsec1/xml-sec-xmlsec1.pc.in
  • docs/README.md
  • docs/c-api.md
  • docs/features.md
  • docs/migration-libxmlsec1.md
  • scripts/patches/xmloxide-0.5.0.patch
  • src/document.rs
  • src/document/external.rs
  • src/document/owned_tree.rs
  • src/document/owned_tree/ids.rs
  • src/document/owned_tree/tests.rs
  • src/lib.rs
  • src/parser_xmloxide/documentation_tests.rs
  • src/parser_xmloxide/lib.rs
  • src/parser_xmloxide/serial/xml.rs
  • src/xml/dom/mod.rs
  • src/xml/dom/storage/names.rs
  • src/xml/dom/xmloxide.rs
  • tools/xml-sec-tools/src/capi.rs
  • tools/xml-sec-tools/src/capi/tests.rs
  • tools/xml-sec-tools/src/xmlsec1_headers.rs
  • tools/xml-sec-tools/src/xmlsec1_headers/tests.rs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-11T22:24:39.133118Z aab8628 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@polaz
polaz enabled auto-merge (squash) November 11, 2026 22:45
@polaz
polaz merged commit f1c9a92 into main Nov 11, 2026
30 checks passed
@polaz
polaz deleted the feat/#451-owned-tree branch November 11, 2026 22:48
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.

1 participant