Coverage Report

Created: 2025-10-28 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/der-0.7.10/src/error.rs
Line
Count
Source
1
//! Error types.
2
3
pub use core::str::Utf8Error;
4
5
use crate::{Length, Tag};
6
use core::{convert::Infallible, fmt, num::TryFromIntError};
7
8
#[cfg(feature = "oid")]
9
use crate::asn1::ObjectIdentifier;
10
11
#[cfg(feature = "pem")]
12
use crate::pem;
13
14
/// Result type.
15
pub type Result<T> = core::result::Result<T, Error>;
16
17
/// Error type.
18
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
19
pub struct Error {
20
    /// Kind of error.
21
    kind: ErrorKind,
22
23
    /// Position inside of message where error occurred.
24
    position: Option<Length>,
25
}
26
27
impl Error {
28
    /// Create a new [`Error`].
29
0
    pub fn new(kind: ErrorKind, position: Length) -> Error {
30
0
        Error {
31
0
            kind,
32
0
            position: Some(position),
33
0
        }
34
0
    }
35
36
    /// Create a new [`ErrorKind::Incomplete`] for the given length.
37
    ///
38
    /// Computes the expected len as being one greater than `actual_len`.
39
0
    pub fn incomplete(actual_len: Length) -> Self {
40
0
        match actual_len + Length::ONE {
41
0
            Ok(expected_len) => ErrorKind::Incomplete {
42
0
                expected_len,
43
0
                actual_len,
44
0
            }
45
0
            .at(actual_len),
46
0
            Err(err) => err.kind().at(actual_len),
47
        }
48
0
    }
49
50
    /// Get the [`ErrorKind`] which occurred.
51
0
    pub fn kind(self) -> ErrorKind {
52
0
        self.kind
53
0
    }
54
55
    /// Get the position inside of the message where the error occurred.
56
0
    pub fn position(self) -> Option<Length> {
57
0
        self.position
58
0
    }
59
60
    /// For errors occurring inside of a nested message, extend the position
61
    /// count by the location where the nested message occurs.
62
0
    pub(crate) fn nested(self, nested_position: Length) -> Self {
63
        // TODO(tarcieri): better handle length overflows occurring in this calculation?
64
0
        let position = (nested_position + self.position.unwrap_or_default()).ok();
65
66
0
        Self {
67
0
            kind: self.kind,
68
0
            position,
69
0
        }
70
0
    }
71
}
72
73
#[cfg(feature = "std")]
74
impl std::error::Error for Error {}
75
76
impl fmt::Display for Error {
77
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78
0
        write!(f, "{}", self.kind)?;
79
80
0
        if let Some(pos) = self.position {
81
0
            write!(f, " at DER byte {}", pos)?;
82
0
        }
83
84
0
        Ok(())
85
0
    }
86
}
87
88
impl From<ErrorKind> for Error {
89
0
    fn from(kind: ErrorKind) -> Error {
90
0
        Error {
91
0
            kind,
92
0
            position: None,
93
0
        }
94
0
    }
95
}
96
97
impl From<Infallible> for Error {
98
0
    fn from(_: Infallible) -> Error {
99
0
        unreachable!()
100
    }
101
}
102
103
impl From<TryFromIntError> for Error {
104
0
    fn from(_: TryFromIntError) -> Error {
105
0
        Error {
106
0
            kind: ErrorKind::Overflow,
107
0
            position: None,
108
0
        }
109
0
    }
110
}
111
112
impl From<Utf8Error> for Error {
113
0
    fn from(err: Utf8Error) -> Error {
114
0
        Error {
115
0
            kind: ErrorKind::Utf8(err),
116
0
            position: None,
117
0
        }
118
0
    }
119
}
120
121
#[cfg(feature = "alloc")]
122
impl From<alloc::string::FromUtf8Error> for Error {
123
0
    fn from(err: alloc::string::FromUtf8Error) -> Error {
124
0
        ErrorKind::Utf8(err.utf8_error()).into()
125
0
    }
126
}
127
128
#[cfg(feature = "oid")]
129
impl From<const_oid::Error> for Error {
130
    fn from(_: const_oid::Error) -> Error {
131
        ErrorKind::OidMalformed.into()
132
    }
133
}
134
135
#[cfg(feature = "pem")]
136
impl From<pem::Error> for Error {
137
    fn from(err: pem::Error) -> Error {
138
        ErrorKind::Pem(err).into()
139
    }
140
}
141
142
#[cfg(feature = "std")]
143
impl From<std::io::Error> for Error {
144
    fn from(err: std::io::Error) -> Error {
145
        match err.kind() {
146
            std::io::ErrorKind::NotFound => ErrorKind::FileNotFound,
147
            std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
148
            other => ErrorKind::Io(other),
149
        }
150
        .into()
151
    }
152
}
153
154
#[cfg(feature = "time")]
155
impl From<time::error::ComponentRange> for Error {
156
    fn from(_: time::error::ComponentRange) -> Error {
157
        ErrorKind::DateTime.into()
158
    }
159
}
160
161
/// Error type.
162
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
163
#[non_exhaustive]
164
pub enum ErrorKind {
165
    /// Date-and-time related errors.
166
    DateTime,
167
168
    /// This error indicates a previous DER parsing operation resulted in
169
    /// an error and tainted the state of a `Decoder` or `Encoder`.
170
    ///
171
    /// Once this occurs, the overall operation has failed and cannot be
172
    /// subsequently resumed.
173
    Failed,
174
175
    /// File not found error.
176
    #[cfg(feature = "std")]
177
    FileNotFound,
178
179
    /// Message is incomplete and does not contain all of the expected data.
180
    Incomplete {
181
        /// Expected message length.
182
        ///
183
        /// Note that this length represents a *minimum* lower bound on how
184
        /// much additional data is needed to continue parsing the message.
185
        ///
186
        /// It's possible upon subsequent message parsing that the parser will
187
        /// discover even more data is needed.
188
        expected_len: Length,
189
190
        /// Actual length of the message buffer currently being processed.
191
        actual_len: Length,
192
    },
193
194
    /// I/O errors.
195
    #[cfg(feature = "std")]
196
    Io(std::io::ErrorKind),
197
198
    /// Indefinite length disallowed.
199
    IndefiniteLength,
200
201
    /// Incorrect length for a given field.
202
    Length {
203
        /// Tag of the value being decoded.
204
        tag: Tag,
205
    },
206
207
    /// Message is not canonically encoded.
208
    Noncanonical {
209
        /// Tag of the value which is not canonically encoded.
210
        tag: Tag,
211
    },
212
213
    /// OID is improperly encoded.
214
    OidMalformed,
215
216
    /// Unknown OID.
217
    ///
218
    /// This error is intended to be used by libraries which parse DER-based
219
    /// formats which encounter unknown or unsupported OID libraries.
220
    ///
221
    /// It enables passing back the OID value to the caller, which allows them
222
    /// to determine which OID(s) are causing the error (and then potentially
223
    /// contribute upstream support for algorithms they care about).
224
    #[cfg(feature = "oid")]
225
    OidUnknown {
226
        /// OID value that was unrecognized by a parser for a DER-based format.
227
        oid: ObjectIdentifier,
228
    },
229
230
    /// `SET` cannot contain duplicates.
231
    SetDuplicate,
232
233
    /// `SET` ordering error: items not in canonical order.
234
    SetOrdering,
235
236
    /// Integer overflow occurred (library bug!).
237
    Overflow,
238
239
    /// Message is longer than this library's internal limits support.
240
    Overlength,
241
242
    /// PEM encoding errors.
243
    #[cfg(feature = "pem")]
244
    Pem(pem::Error),
245
246
    /// Permission denied reading file.
247
    #[cfg(feature = "std")]
248
    PermissionDenied,
249
250
    /// Reader does not support the requested operation.
251
    Reader,
252
253
    /// Unknown tag mode.
254
    TagModeUnknown,
255
256
    /// Invalid tag number.
257
    ///
258
    /// The "tag number" is the lower 5-bits of a tag's octet.
259
    /// This error occurs in the case that all 5-bits are set to `1`,
260
    /// which indicates a multi-byte tag which is unsupported by this library.
261
    TagNumberInvalid,
262
263
    /// Unexpected tag.
264
    TagUnexpected {
265
        /// Tag the decoder was expecting (if there is a single such tag).
266
        ///
267
        /// `None` if multiple tags are expected/allowed, but the `actual` tag
268
        /// does not match any of them.
269
        expected: Option<Tag>,
270
271
        /// Actual tag encountered in the message.
272
        actual: Tag,
273
    },
274
275
    /// Unknown/unsupported tag.
276
    TagUnknown {
277
        /// Raw byte value of the tag.
278
        byte: u8,
279
    },
280
281
    /// Undecoded trailing data at end of message.
282
    TrailingData {
283
        /// Length of the decoded data.
284
        decoded: Length,
285
286
        /// Total length of the remaining data left in the buffer.
287
        remaining: Length,
288
    },
289
290
    /// UTF-8 errors.
291
    Utf8(Utf8Error),
292
293
    /// Unexpected value.
294
    Value {
295
        /// Tag of the unexpected value.
296
        tag: Tag,
297
    },
298
}
299
300
impl ErrorKind {
301
    /// Annotate an [`ErrorKind`] with context about where it occurred,
302
    /// returning an error.
303
0
    pub fn at(self, position: Length) -> Error {
304
0
        Error::new(self, position)
305
0
    }
306
}
307
308
impl fmt::Display for ErrorKind {
309
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310
0
        match self {
311
0
            ErrorKind::DateTime => write!(f, "date/time error"),
312
0
            ErrorKind::Failed => write!(f, "operation failed"),
313
            #[cfg(feature = "std")]
314
            ErrorKind::FileNotFound => write!(f, "file not found"),
315
            ErrorKind::Incomplete {
316
0
                expected_len,
317
0
                actual_len,
318
0
            } => write!(
319
0
                f,
320
0
                "ASN.1 DER message is incomplete: expected {}, actual {}",
321
                expected_len, actual_len
322
            ),
323
            #[cfg(feature = "std")]
324
            ErrorKind::Io(err) => write!(f, "I/O error: {:?}", err),
325
0
            ErrorKind::IndefiniteLength => write!(f, "indefinite length disallowed"),
326
0
            ErrorKind::Length { tag } => write!(f, "incorrect length for {}", tag),
327
0
            ErrorKind::Noncanonical { tag } => {
328
0
                write!(f, "ASN.1 {} not canonically encoded as DER", tag)
329
            }
330
0
            ErrorKind::OidMalformed => write!(f, "malformed OID"),
331
            #[cfg(feature = "oid")]
332
            ErrorKind::OidUnknown { oid } => {
333
                write!(f, "unknown/unsupported OID: {}", oid)
334
            }
335
0
            ErrorKind::SetDuplicate => write!(f, "SET OF contains duplicate"),
336
0
            ErrorKind::SetOrdering => write!(f, "SET OF ordering error"),
337
0
            ErrorKind::Overflow => write!(f, "integer overflow"),
338
0
            ErrorKind::Overlength => write!(f, "ASN.1 DER message is too long"),
339
            #[cfg(feature = "pem")]
340
            ErrorKind::Pem(e) => write!(f, "PEM error: {}", e),
341
            #[cfg(feature = "std")]
342
            ErrorKind::PermissionDenied => write!(f, "permission denied"),
343
0
            ErrorKind::Reader => write!(f, "reader does not support the requested operation"),
344
0
            ErrorKind::TagModeUnknown => write!(f, "unknown tag mode"),
345
0
            ErrorKind::TagNumberInvalid => write!(f, "invalid tag number"),
346
0
            ErrorKind::TagUnexpected { expected, actual } => {
347
0
                write!(f, "unexpected ASN.1 DER tag: ")?;
348
349
0
                if let Some(tag) = expected {
350
0
                    write!(f, "expected {}, ", tag)?;
351
0
                }
352
353
0
                write!(f, "got {}", actual)
354
            }
355
0
            ErrorKind::TagUnknown { byte } => {
356
0
                write!(f, "unknown/unsupported ASN.1 DER tag: 0x{:02x}", byte)
357
            }
358
0
            ErrorKind::TrailingData { decoded, remaining } => {
359
0
                write!(
360
0
                    f,
361
0
                    "trailing data at end of DER message: decoded {} bytes, {} bytes remaining",
362
                    decoded, remaining
363
                )
364
            }
365
0
            ErrorKind::Utf8(e) => write!(f, "{}", e),
366
0
            ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {}", tag),
367
        }
368
0
    }
369
}