1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// SPDX-License-Identifier: Apache-2.0
//! Panic-shielded `quick-xml` deserialisation helper.
//!
//! Every attacker-reachable XML body in this crate (the Maven `pom.xml`
//! upload boundary and the `maven-metadata.xml` PUT/GET boundary) is
//! deserialised through [`from_str_panic_safe`].
//!
//! # Why `catch_unwind`
//!
//! `quick_xml::de` 0.39.2 hits an `unreachable!()` macro at
//! `quick-xml-0.39.2/src/de/mod.rs:2903:37` (`internal error: entered
//! unreachable code`) on certain malformed inputs (e.g. mixed-token
//! `<><groupId\tp...\n<!DOCTYPe\t;:="0"1"...` shapes — see the
//! 2026-05-15 fuzz artifact `crash-1ceeadf1`). That panic propagates
//! past any `?`/`map_err` conversion and aborts the request thread.
//! Production callers (the `ferro-maven-server` registry PUT handlers)
//! must never abort on attacker-supplied bodies, so the panic is
//! converted into a caller-supplied error value just like every other
//! parse failure.
use AssertUnwindSafe;
use DeserializeOwned;
/// Deserialise `xml` into `T`, converting both ordinary parse errors
/// **and** `quick-xml` deserialiser panics into `E` via `on_err`.
///
/// `on_err` is called with a human-readable message:
///
/// - `"XML parse failed: {e}"` when `quick-xml` returns a parse error;
/// - `"XML parser panicked on malformed input: {msg}"` when `quick-xml`
/// hits its internal `unreachable!()` (the downcasted panic payload
/// is preserved for debugging).
///
/// # Errors
///
/// Returns `Err(on_err(..))` on any parse error or recovered panic.