@@ -41,6 +41,25 @@ pub enum Item {
41
41
Crl ( CertificateRevocationListDer < ' static > ) ,
42
42
}
43
43
44
+ /// Errors that may arise when parsing the contents of a PEM file
45
+ #[ derive( Debug , PartialEq ) ]
46
+ pub enum Error {
47
+ /// a section is missing its "END marker" line
48
+ MissingSectionEnd {
49
+ /// the expected "END marker" line that was not found
50
+ end_marker : Vec < u8 > ,
51
+ } ,
52
+
53
+ /// syntax error found in the line that starts a new section
54
+ IllegalSectionStart {
55
+ /// line that contains the syntax error
56
+ line : Vec < u8 > ,
57
+ } ,
58
+
59
+ /// base64 decode error
60
+ Base64Decode ( String ) ,
61
+ }
62
+
44
63
/// Extract and decode the next PEM section from `rd`.
45
64
///
46
65
/// - Ok(None) is returned if there is no PEM section read from `rd`.
@@ -64,9 +83,30 @@ pub fn read_one(rd: &mut dyn io::BufRead) -> Result<Option<Item>, io::Error> {
64
83
Some ( line. as_slice ( ) )
65
84
} ;
66
85
67
- match read_one_impl ( next_line, & mut section, & mut b64buf) ? {
68
- ControlFlow :: Break ( opt) => return Ok ( opt) ,
69
- ControlFlow :: Continue ( ( ) ) => continue ,
86
+ match read_one_impl ( next_line, & mut section, & mut b64buf) {
87
+ Ok ( ControlFlow :: Break ( opt) ) => return Ok ( opt) ,
88
+ Ok ( ControlFlow :: Continue ( ( ) ) ) => continue ,
89
+ Err ( e) => {
90
+ return Err ( match e {
91
+ Error :: MissingSectionEnd { end_marker } => io:: Error :: new (
92
+ ErrorKind :: InvalidData ,
93
+ format ! (
94
+ "section end {:?} missing" ,
95
+ String :: from_utf8_lossy( & end_marker)
96
+ ) ,
97
+ ) ,
98
+
99
+ Error :: IllegalSectionStart { line } => io:: Error :: new (
100
+ ErrorKind :: InvalidData ,
101
+ format ! (
102
+ "illegal section start: {:?}" ,
103
+ String :: from_utf8_lossy( & line)
104
+ ) ,
105
+ ) ,
106
+
107
+ Error :: Base64Decode ( err) => io:: Error :: new ( ErrorKind :: InvalidData , err) ,
108
+ } ) ;
109
+ }
70
110
}
71
111
}
72
112
}
@@ -75,19 +115,13 @@ fn read_one_impl(
75
115
next_line : Option < & [ u8 ] > ,
76
116
section : & mut Option < ( Vec < u8 > , Vec < u8 > ) > ,
77
117
b64buf : & mut Vec < u8 > ,
78
- ) -> Result < ControlFlow < Option < Item > , ( ) > , io :: Error > {
118
+ ) -> Result < ControlFlow < Option < Item > , ( ) > , Error > {
79
119
let line = if let Some ( line) = next_line {
80
120
line
81
121
} else {
82
122
// EOF
83
123
return match section. take ( ) {
84
- Some ( ( _, end_marker) ) => Err ( io:: Error :: new (
85
- ErrorKind :: InvalidData ,
86
- format ! (
87
- "section end {:?} missing" ,
88
- String :: from_utf8_lossy( & end_marker)
89
- ) ,
90
- ) ) ,
124
+ Some ( ( _, end_marker) ) => Err ( Error :: MissingSectionEnd { end_marker } ) ,
91
125
None => Ok ( ControlFlow :: Break ( None ) ) ,
92
126
} ;
93
127
} ;
@@ -106,10 +140,9 @@ fn read_one_impl(
106
140
}
107
141
108
142
if trailer != 5 {
109
- return Err ( io:: Error :: new (
110
- ErrorKind :: InvalidData ,
111
- format ! ( "illegal section start: {:?}" , String :: from_utf8_lossy( line) ) ,
112
- ) ) ;
143
+ return Err ( Error :: IllegalSectionStart {
144
+ line : line. to_vec ( ) ,
145
+ } ) ;
113
146
}
114
147
115
148
let ty = & line[ 11 ..pos] ;
@@ -125,7 +158,7 @@ fn read_one_impl(
125
158
if line. starts_with ( end_marker) {
126
159
let der = base64:: ENGINE
127
160
. decode ( & b64buf)
128
- . map_err ( |err| io :: Error :: new ( ErrorKind :: InvalidData , err) ) ?;
161
+ . map_err ( |err| Error :: Base64Decode ( format ! ( "{ err:?}" ) ) ) ?;
129
162
130
163
let item = match section_type. as_slice ( ) {
131
164
b"CERTIFICATE" => Some ( Item :: X509Certificate ( der. into ( ) ) ) ,
0 commit comments