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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// SPDX-License-Identifier: Apache-2.0
/// Errors generated by the numeric type impls
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
/// Multitrait decode error
#[error(transparent)]
Multitrait(#[from] multi_trait::Error),
/// Multicodec decode error
#[error(transparent)]
Multicodec(#[from] multi_codec::Error),
/// `BaseEncoded` error
#[error(transparent)]
BaseEncoded(#[from] BaseEncodedError),
/// `BaseEncoder` error
#[error(transparent)]
BaseEncoder(#[from] BaseEncoderError),
/// Custom error for inner types to use when nothing else works
#[error("Custom error: {0}")]
Custom(String),
/// Insufficient data available for the claimed length
///
/// This error occurs when a varint length claim exceeds the available buffer size.
/// This prevents buffer overflow attacks where an attacker claims a large length
/// but provides minimal data.
///
/// # Security
///
/// This validation prevents CWE-125 (Out-of-bounds Read) vulnerabilities.
///
/// # Example
///
/// ```rust
/// use multi_util::Error;
///
/// // This would trigger InsufficientData:
/// // Varint claims 1000 bytes but only 3 bytes available
/// ```
#[error("insufficient data: expected {expected} bytes, but only {actual} bytes available")]
InsufficientData {
/// The number of bytes claimed by the length prefix
expected: usize,
/// The actual number of bytes available in the buffer
actual: usize,
},
/// Decoded length exceeds the configured maximum
///
/// This error occurs when a varint length claim exceeds [`crate::varbytes::MAX_DECODED_SIZE`].
/// Enforcing an upper bound on a single decoded `Varbytes` value prevents a peer that supplies
/// a legitimately-sized buffer from causing the decoder to allocate an arbitrarily large
/// `Vec<u8>` (`DoS` via memory exhaustion). The default ceiling is 16 MiB, which comfortably
/// exceeds every legitimate multiformat payload in this stack while still bounding the
/// worst-case allocation for untrusted wire data.
///
/// # Security
///
/// This validation mitigates CWE-400 (Uncontrolled Resource Consumption).
#[error("decoded length {claimed} exceeds maximum {max}")]
InputTooLarge {
/// The number of bytes claimed by the length prefix
claimed: usize,
/// The configured maximum decoded size
max: usize,
},
}
impl Error {
/// create a custom error instance
#[must_use]
pub fn custom(s: &str) -> Self {
Self::Custom(s.to_string())
}
}
/// Errors generated by the base encoding smart pointer
#[derive(Clone, Debug, thiserror::Error)]
#[non_exhaustive]
pub enum BaseEncodedError {
/// `BaseEncoder` error
#[error(transparent)]
BaseEncoder(#[from] BaseEncoderError),
/// Value decoding failed
#[error("Failed to decode the tagged value")]
ValueFailed,
}
/// Errors generated by the base encoding smart pointer
#[derive(Clone, Debug, thiserror::Error)]
#[non_exhaustive]
pub enum BaseEncoderError {
/// Multibase decode error
#[error(transparent)]
Multibase(#[from] multi_base::Error),
/// Base58 decode error
#[error("Base58 error: {0}")]
Base58(String),
}