#970: Add NsReader::resolver_mut() and NamespaceResolver::{max_declarations_per_element, set_max_declarations_per_element}.
Bug Fixes
#969: Attributes (and anything that iterates BytesStart::attributes() with the default with_checks(true)) no longer takes O(N²) time on a start tag with a large number of attributes. Small tags keep the previous linear scan; larger ones switch to a 64-bit hash pre-filter, so the whole tag is O(N). The exact AttrError::Duplicated(new, prev) positions are unchanged.
#970: NamespaceResolver::push (and hence every NsReaderStart/Empty event) now rejects a start tag that declares more than DEFAULT_MAX_DECLARATIONS_PER_ELEMENT (256) xmlns / xmlns:* namespace bindings, returning the new NamespaceError::TooManyDeclarations. Previously push allocated one NamespaceBinding per declaration with no upper bound, before the event was returned to the caller, so an NsReader consumer could not bound its memory exposure on untrusted input. The limit is configurable via NamespaceResolver::set_max_declarations_per_element (use usize::MAX to disable).
v0.40.1 - Fix rarely possible serde deserialization panic
What's Changed
#964: Fix unreachable!() panic in the serde deserializer when a DOCTYPE declaration appears between two text runs inside an element (e.g. <a>x<!DOCTYPE y>z</a>). The DOCTYPE used to break drain_text's consecutive-text merge, so two DeEvent::Text events reached read_text and tripped its "Cannot be two consequent Text events" invariant. DOCTYPE is now treated as transparent during text drain — it still goes through the entity resolver, but the surrounding text is merged into one run. Discovered via libFuzzer on a real-world SAML deserializer harness.
v0.40.0 - UTF-16 and ISO-2022-JP encodings supported
What's Changed
MSRV bumped to 1.79.
Now quick-xml supports the UTF-16 and ISO-2022-JP encoded documents. See the new DecodingReader type.
New Features
#956: Add DecodingReader, a BufRead adapter that auto-detects encoding from BOM or XML declaration and transcodes to UTF-8. Enabled by the encoding feature.
#938: Add new enumeration XmlVersion and typified getter BytesDecl::xml_version().
#938: Add new error variant IllFormedError::UnknownVersion.
#371: Add new error variant EscapeError::TooManyNestedEntities.
#371: Improved compliance with the XML attribute value normalization process by adding
#970: Add NsReader::resolver_mut() and
NamespaceResolver::{max_declarations_per_element, set_max_declarations_per_element}.
Bug Fixes
#969: Attributes (and anything that iterates BytesStart::attributes()
with the default with_checks(true)) no longer takes O(N²) time on a start
tag with a large number of attributes. Small tags keep the previous linear
scan; larger ones switch to a 64-bit hash pre-filter, so the whole tag is
O(N). The exact AttrError::Duplicated(new, prev) positions are unchanged.
#970: NamespaceResolver::push (and hence every NsReaderStart/Empty
event) now rejects a start tag that declares more than
DEFAULT_MAX_DECLARATIONS_PER_ELEMENT (256) xmlns / xmlns:* namespace
bindings, returning the new NamespaceError::TooManyDeclarations. Previously
push allocated one NamespaceBinding per declaration with no upper bound,
before the event was returned to the caller, so an NsReader consumer could
not bound its memory exposure on untrusted input. The limit is configurable
via NamespaceResolver::set_max_declarations_per_element (use usize::MAX
to disable).
#964: Fix unreachable!() panic in the serde deserializer when a DOCTYPE
declaration appears between two text runs inside an element (e.g.
<a>x<!DOCTYPE y>z</a>). The DOCTYPE used to break drain_text's
consecutive-text merge, so two DeEvent::Text events reached
read_text and tripped its "Cannot be two consequent Text events"
invariant. DOCTYPE is now treated as transparent during text drain —
it still goes through the entity resolver, but the surrounding text
is merged into one run. Discovered via libFuzzer on a real-world
SAML deserializer harness.
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebase will rebase this PR
@dependabot recreate will recreate this PR, overwriting any edits that have been made to it
@dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
@dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
@dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
@dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Bumps [quick-xml](https://github.com/tafia/quick-xml) from 0.36.2 to 0.41.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/tafia/quick-xml/releases">quick-xml's releases</a>.</em></p>
<blockquote>
<h2>v0.41.0 - Secuirity fixes</h2>
<h2>What's Changed</h2>
<h3>New Features</h3>
<ul>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/970">#970</a>: Add <code>NsReader::resolver_mut()</code> and <code>NamespaceResolver::{max_declarations_per_element, set_max_declarations_per_element}</code>.</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/969">#969</a>: <code>Attributes</code> (and anything that iterates <code>BytesStart::attributes()</code> with the default <code>with_checks(true)</code>) no longer takes O(N²) time on a start tag with a large number of attributes. Small tags keep the previous linear scan; larger ones switch to a 64-bit hash pre-filter, so the whole tag is O(N). The exact <code>AttrError::Duplicated(new, prev)</code> positions are unchanged.</li>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/970">#970</a>: <code>NamespaceResolver::push</code> (and hence every <code>NsReader</code> <code>Start</code>/<code>Empty</code> event) now rejects a start tag that declares more than <code>DEFAULT_MAX_DECLARATIONS_PER_ELEMENT</code> (256) <code>xmlns</code> / <code>xmlns:*</code> namespace bindings, returning the new <code>NamespaceError::TooManyDeclarations</code>. Previously <code>push</code> allocated one <code>NamespaceBinding</code> per declaration with no upper bound, before the event was returned to the caller, so an <code>NsReader</code> consumer could not bound its memory exposure on untrusted input. The limit is configurable via <code>NamespaceResolver::set_max_declarations_per_element</code> (use <code>usize::MAX</code> to disable).</li>
</ul>
<p><a href="https://redirect.github.com/tafia/quick-xml/issues/969">#969</a>: <a href="https://redirect.github.com/tafia/quick-xml/issues/969">tafia/quick-xml#969</a>
<a href="https://redirect.github.com/tafia/quick-xml/issues/970">#970</a>: <a href="https://redirect.github.com/tafia/quick-xml/issues/970">tafia/quick-xml#970</a></p>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/qifan-sailboat"><code>@qifan-sailboat</code></a> made their first contribution in <a href="https://redirect.github.com/tafia/quick-xml/pull/972">tafia/quick-xml#972</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/tafia/quick-xml/compare/v0.40.1...v0.41.0">https://github.com/tafia/quick-xml/compare/v0.40.1...v0.41.0</a></p>
<h2>v0.40.1 - Fix rarely possible serde deserialization panic</h2>
<h2>What's Changed</h2>
<ul>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/964">#964</a>: Fix <code>unreachable!()</code> panic in the serde deserializer when a DOCTYPE declaration appears between two text runs inside an element (e.g. <code><a>x<!DOCTYPE y>z</a></code>). The DOCTYPE used to break <code>drain_text</code>'s consecutive-text merge, so two <code>DeEvent::Text</code> events reached <code>read_text</code> and tripped its "Cannot be two consequent Text events" invariant. DOCTYPE is now treated as transparent during text drain — it still goes through the entity resolver, but the surrounding text is merged into one run. Discovered via libFuzzer on a real-world SAML deserializer harness.</li>
</ul>
<p><a href="https://redirect.github.com/tafia/quick-xml/issues/964">#964</a>: <a href="https://redirect.github.com/tafia/quick-xml/pull/964">tafia/quick-xml#964</a></p>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/williamareynolds"><code>@williamareynolds</code></a> made their first contribution in <a href="https://redirect.github.com/tafia/quick-xml/pull/964">tafia/quick-xml#964</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/tafia/quick-xml/compare/v0.40.0...v0.40.1">https://github.com/tafia/quick-xml/compare/v0.40.0...v0.40.1</a></p>
<h2>v0.40.0 - UTF-16 and ISO-2022-JP encodings supported</h2>
<h2>What's Changed</h2>
<p>MSRV bumped to 1.79.</p>
<p>Now <code>quick-xml</code> supports the UTF-16 and ISO-2022-JP encoded documents. See the new <code>DecodingReader</code> type.</p>
<h3>New Features</h3>
<ul>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/956">#956</a>: Add <code>DecodingReader</code>, a <code>BufRead</code> adapter that auto-detects encoding from BOM or XML declaration and transcodes to UTF-8. Enabled by the <code>encoding</code> feature.</li>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/938">#938</a>: Add new enumeration <code>XmlVersion</code> and typified getter <code>BytesDecl::xml_version()</code>.</li>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/938">#938</a>: Add new error variant <code>IllFormedError::UnknownVersion</code>.</li>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/371">#371</a>: Add new error variant <code>EscapeError::TooManyNestedEntities</code>.</li>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/371">#371</a>: Improved compliance with the XML attribute value normalization process by adding
<ul>
<li><code>Attribute::normalized_value()</code></li>
<li><code>Attribute::normalized_value_with()</code></li>
<li><code>Attribute::decoded_and_normalized_value()</code></li>
<li><code>Attribute::decoded_and_normalized_value_with()</code></li>
</ul>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/tafia/quick-xml/blob/master/Changelog.md">quick-xml's changelog</a>.</em></p>
<blockquote>
<h2>0.41.0 -- 2026-06-29</h2>
<h3>New Features</h3>
<ul>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/970">#970</a>: Add <code>NsReader::resolver_mut()</code> and
<code>NamespaceResolver::{max_declarations_per_element, set_max_declarations_per_element}</code>.</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/969">#969</a>: <code>Attributes</code> (and anything that iterates <code>BytesStart::attributes()</code>
with the default <code>with_checks(true)</code>) no longer takes O(N²) time on a start
tag with a large number of attributes. Small tags keep the previous linear
scan; larger ones switch to a 64-bit hash pre-filter, so the whole tag is
O(N). The exact <code>AttrError::Duplicated(new, prev)</code> positions are unchanged.</li>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/970">#970</a>: <code>NamespaceResolver::push</code> (and hence every <code>NsReader</code> <code>Start</code>/<code>Empty</code>
event) now rejects a start tag that declares more than
<code>DEFAULT_MAX_DECLARATIONS_PER_ELEMENT</code> (256) <code>xmlns</code> / <code>xmlns:*</code> namespace
bindings, returning the new <code>NamespaceError::TooManyDeclarations</code>. Previously
<code>push</code> allocated one <code>NamespaceBinding</code> per declaration with no upper bound,
before the event was returned to the caller, so an <code>NsReader</code> consumer could
not bound its memory exposure on untrusted input. The limit is configurable
via <code>NamespaceResolver::set_max_declarations_per_element</code> (use <code>usize::MAX</code>
to disable).</li>
</ul>
<p><a href="https://redirect.github.com/tafia/quick-xml/issues/969">#969</a>: <a href="https://redirect.github.com/tafia/quick-xml/issues/969">tafia/quick-xml#969</a>
<a href="https://redirect.github.com/tafia/quick-xml/issues/970">#970</a>: <a href="https://redirect.github.com/tafia/quick-xml/issues/970">tafia/quick-xml#970</a></p>
<h2>0.40.1 -- 2026-05-15</h2>
<h3>Bug Fixes</h3>
<ul>
<li><a href="https://redirect.github.com/tafia/quick-xml/issues/964">#964</a>: Fix <code>unreachable!()</code> panic in the serde deserializer when a DOCTYPE
declaration appears between two text runs inside an element (e.g.
<code><a>x<!DOCTYPE y>z</a></code>). The DOCTYPE used to break <code>drain_text</code>'s
consecutive-text merge, so two <code>DeEvent::Text</code> events reached
<code>read_text</code> and tripped its "Cannot be two consequent Text events"
invariant. DOCTYPE is now treated as transparent during text drain —
it still goes through the entity resolver, but the surrounding text
is merged into one run. Discovered via libFuzzer on a real-world
SAML deserializer harness.</li>
</ul>
<p><a href="https://redirect.github.com/tafia/quick-xml/issues/964">#964</a>: <a href="https://redirect.github.com/tafia/quick-xml/pull/964">tafia/quick-xml#964</a></p>
<h3>Misc Changes</h3>
<h2>0.40.0 -- 2026-05-11</h2>
<p>MSRV bumped to 1.79.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/tafia/quick-xml/commit/4deda08abeffdc188c269360229cf47e12a77a9f"><code>4deda08</code></a> Release 0.41.0</li>
<li><a href="https://github.com/tafia/quick-xml/commit/1b3b73b4cc6e1e5c2f40fb1cb955d3bbe264368f"><code>1b3b73b</code></a> Remove unused argument to <code>check!</code></li>
<li><a href="https://github.com/tafia/quick-xml/commit/07f3db8343cf152f5bc3483ef5b3164582489bea"><code>07f3db8</code></a> Fix O(N²) duplicate-attribute check in <code>Attributes</code> iterator</li>
<li><a href="https://github.com/tafia/quick-xml/commit/7ca25266e94987210daa864889ab15c9332c8a2a"><code>7ca2526</code></a> Cap namespace declarations per element in <code>NamespaceResolver::push</code></li>
<li><a href="https://github.com/tafia/quick-xml/commit/9aaea9281d346ec0249c679639a15eef8f9cbb18"><code>9aaea92</code></a> Release 0.40.1</li>
<li><a href="https://github.com/tafia/quick-xml/commit/ce488bca4e85427e5ab431e7c9e6f15b9ed73135"><code>ce488bc</code></a> Merge pull request <a href="https://redirect.github.com/tafia/quick-xml/issues/964">#964</a> from williamareynolds/fix/de-doctype-in-text-unreachable</li>
<li><a href="https://github.com/tafia/quick-xml/commit/e00ae5c749155ee3001bd4629a12282011a0fdfb"><code>e00ae5c</code></a> Fix unreachable!() panic when DOCTYPE appears between text runs in element co...</li>
<li><a href="https://github.com/tafia/quick-xml/commit/2778564d592ca25d6315ea20b5105c74addfce5e"><code>2778564</code></a> Release 0.40.0</li>
<li><a href="https://github.com/tafia/quick-xml/commit/393db036811e7473b22d875109cd07acb183580f"><code>393db03</code></a> Merge pull request <a href="https://redirect.github.com/tafia/quick-xml/issues/962">#962</a> from Mingun/prepare-0.40</li>
<li><a href="https://github.com/tafia/quick-xml/commit/a27709a457126f129b06d20309316be74056234c"><code>a27709a</code></a> Fix misprint in code example</li>
<li>Additional commits viewable in <a href="https://github.com/tafia/quick-xml/compare/v0.36.2...v0.41.0">compare view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
</details>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Bumps quick-xml from 0.36.2 to 0.41.0.
Release notes
Sourced from quick-xml's releases.
... (truncated)
Changelog
Sourced from quick-xml's changelog.
... (truncated)
Commits
4deda08Release 0.41.01b3b73bRemove unused argument tocheck!07f3db8Fix O(N²) duplicate-attribute check inAttributesiterator7ca2526Cap namespace declarations per element inNamespaceResolver::push9aaea92Release 0.40.1ce488bcMerge pull request #964 from williamareynolds/fix/de-doctype-in-text-unreachablee00ae5cFix unreachable!() panic when DOCTYPE appears between text runs in element co...2778564Release 0.40.0393db03Merge pull request #962 from Mingun/prepare-0.40a27709aFix misprint in code exampleDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)