• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::engine::{general_purpose::STANDARD, DecodeEstimate, Engine};
2 #[cfg(any(feature = "alloc", feature = "std", test))]
3 use alloc::vec::Vec;
4 use core::fmt;
5 #[cfg(any(feature = "std", test))]
6 use std::error;
7 
8 /// Errors that can occur while decoding.
9 #[derive(Clone, Debug, PartialEq, Eq)]
10 pub enum DecodeError {
11     /// An invalid byte was found in the input. The offset and offending byte are provided.
12     /// Padding characters (`=`) interspersed in the encoded form will be treated as invalid bytes.
13     InvalidByte(usize, u8),
14     /// The length of the input is invalid.
15     /// A typical cause of this is stray trailing whitespace or other separator bytes.
16     /// In the case where excess trailing bytes have produced an invalid length *and* the last byte
17     /// is also an invalid base64 symbol (as would be the case for whitespace, etc), `InvalidByte`
18     /// will be emitted instead of `InvalidLength` to make the issue easier to debug.
19     InvalidLength,
20     /// The last non-padding input symbol's encoded 6 bits have nonzero bits that will be discarded.
21     /// This is indicative of corrupted or truncated Base64.
22     /// Unlike `InvalidByte`, which reports symbols that aren't in the alphabet, this error is for
23     /// symbols that are in the alphabet but represent nonsensical encodings.
24     InvalidLastSymbol(usize, u8),
25     /// The nature of the padding was not as configured: absent or incorrect when it must be
26     /// canonical, or present when it must be absent, etc.
27     InvalidPadding,
28 }
29 
30 impl fmt::Display for DecodeError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result31     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32         match *self {
33             Self::InvalidByte(index, byte) => write!(f, "Invalid byte {}, offset {}.", byte, index),
34             Self::InvalidLength => write!(f, "Encoded text cannot have a 6-bit remainder."),
35             Self::InvalidLastSymbol(index, byte) => {
36                 write!(f, "Invalid last symbol {}, offset {}.", byte, index)
37             }
38             Self::InvalidPadding => write!(f, "Invalid padding"),
39         }
40     }
41 }
42 
43 #[cfg(any(feature = "std", test))]
44 impl error::Error for DecodeError {
cause(&self) -> Option<&dyn error::Error>45     fn cause(&self) -> Option<&dyn error::Error> {
46         None
47     }
48 }
49 
50 /// Errors that can occur while decoding into a slice.
51 #[derive(Clone, Debug, PartialEq, Eq)]
52 pub enum DecodeSliceError {
53     /// A [DecodeError] occurred
54     DecodeError(DecodeError),
55     /// The provided slice _may_ be too small.
56     ///
57     /// The check is conservative (assumes the last triplet of output bytes will all be needed).
58     OutputSliceTooSmall,
59 }
60 
61 impl fmt::Display for DecodeSliceError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result62     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63         match self {
64             Self::DecodeError(e) => write!(f, "DecodeError: {}", e),
65             Self::OutputSliceTooSmall => write!(f, "Output slice too small"),
66         }
67     }
68 }
69 
70 #[cfg(any(feature = "std", test))]
71 impl error::Error for DecodeSliceError {
cause(&self) -> Option<&dyn error::Error>72     fn cause(&self) -> Option<&dyn error::Error> {
73         match self {
74             DecodeSliceError::DecodeError(e) => Some(e),
75             DecodeSliceError::OutputSliceTooSmall => None,
76         }
77     }
78 }
79 
80 impl From<DecodeError> for DecodeSliceError {
from(e: DecodeError) -> Self81     fn from(e: DecodeError) -> Self {
82         DecodeSliceError::DecodeError(e)
83     }
84 }
85 
86 /// Decode base64 using the [`STANDARD` engine](STANDARD).
87 ///
88 /// See [Engine::decode].
89 #[deprecated(since = "0.21.0", note = "Use Engine::decode")]
90 #[cfg(any(feature = "alloc", feature = "std", test))]
decode<T: AsRef<[u8]>>(input: T) -> Result<Vec<u8>, DecodeError>91 pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<Vec<u8>, DecodeError> {
92     STANDARD.decode(input)
93 }
94 
95 /// Decode from string reference as octets using the specified [Engine].
96 ///
97 /// See [Engine::decode].
98 ///Returns a `Result` containing a `Vec<u8>`.
99 #[deprecated(since = "0.21.0", note = "Use Engine::decode")]
100 #[cfg(any(feature = "alloc", feature = "std", test))]
decode_engine<E: Engine, T: AsRef<[u8]>>( input: T, engine: &E, ) -> Result<Vec<u8>, DecodeError>101 pub fn decode_engine<E: Engine, T: AsRef<[u8]>>(
102     input: T,
103     engine: &E,
104 ) -> Result<Vec<u8>, DecodeError> {
105     engine.decode(input)
106 }
107 
108 /// Decode from string reference as octets.
109 ///
110 /// See [Engine::decode_vec].
111 #[cfg(any(feature = "alloc", feature = "std", test))]
112 #[deprecated(since = "0.21.0", note = "Use Engine::decode_vec")]
decode_engine_vec<E: Engine, T: AsRef<[u8]>>( input: T, buffer: &mut Vec<u8>, engine: &E, ) -> Result<(), DecodeError>113 pub fn decode_engine_vec<E: Engine, T: AsRef<[u8]>>(
114     input: T,
115     buffer: &mut Vec<u8>,
116     engine: &E,
117 ) -> Result<(), DecodeError> {
118     engine.decode_vec(input, buffer)
119 }
120 
121 /// Decode the input into the provided output slice.
122 ///
123 /// See [Engine::decode_slice].
124 #[deprecated(since = "0.21.0", note = "Use Engine::decode_slice")]
decode_engine_slice<E: Engine, T: AsRef<[u8]>>( input: T, output: &mut [u8], engine: &E, ) -> Result<usize, DecodeSliceError>125 pub fn decode_engine_slice<E: Engine, T: AsRef<[u8]>>(
126     input: T,
127     output: &mut [u8],
128     engine: &E,
129 ) -> Result<usize, DecodeSliceError> {
130     engine.decode_slice(input, output)
131 }
132 
133 /// Returns a conservative estimate of the decoded size of `encoded_len` base64 symbols (rounded up
134 /// to the next group of 3 decoded bytes).
135 ///
136 /// The resulting length will be a safe choice for the size of a decode buffer, but may have up to
137 /// 2 trailing bytes that won't end up being needed.
138 ///
139 /// # Examples
140 ///
141 /// ```
142 /// use base64::decoded_len_estimate;
143 ///
144 /// assert_eq!(3, decoded_len_estimate(1));
145 /// assert_eq!(3, decoded_len_estimate(2));
146 /// assert_eq!(3, decoded_len_estimate(3));
147 /// assert_eq!(3, decoded_len_estimate(4));
148 /// // start of the next quad of encoded symbols
149 /// assert_eq!(6, decoded_len_estimate(5));
150 /// ```
151 ///
152 /// # Panics
153 ///
154 /// Panics if decoded length estimation overflows.
155 /// This would happen for sizes within a few bytes of the maximum value of `usize`.
decoded_len_estimate(encoded_len: usize) -> usize156 pub fn decoded_len_estimate(encoded_len: usize) -> usize {
157     STANDARD
158         .internal_decoded_len_estimate(encoded_len)
159         .decoded_len_estimate()
160 }
161 
162 #[cfg(test)]
163 mod tests {
164     use super::*;
165     use crate::{
166         alphabet,
167         engine::{general_purpose, Config, GeneralPurpose},
168         tests::{assert_encode_sanity, random_engine},
169     };
170     use rand::{
171         distributions::{Distribution, Uniform},
172         Rng, SeedableRng,
173     };
174 
175     #[test]
decode_into_nonempty_vec_doesnt_clobber_existing_prefix()176     fn decode_into_nonempty_vec_doesnt_clobber_existing_prefix() {
177         let mut orig_data = Vec::new();
178         let mut encoded_data = String::new();
179         let mut decoded_with_prefix = Vec::new();
180         let mut decoded_without_prefix = Vec::new();
181         let mut prefix = Vec::new();
182 
183         let prefix_len_range = Uniform::new(0, 1000);
184         let input_len_range = Uniform::new(0, 1000);
185 
186         let mut rng = rand::rngs::SmallRng::from_entropy();
187 
188         for _ in 0..10_000 {
189             orig_data.clear();
190             encoded_data.clear();
191             decoded_with_prefix.clear();
192             decoded_without_prefix.clear();
193             prefix.clear();
194 
195             let input_len = input_len_range.sample(&mut rng);
196 
197             for _ in 0..input_len {
198                 orig_data.push(rng.gen());
199             }
200 
201             let engine = random_engine(&mut rng);
202             engine.encode_string(&orig_data, &mut encoded_data);
203             assert_encode_sanity(&encoded_data, engine.config().encode_padding(), input_len);
204 
205             let prefix_len = prefix_len_range.sample(&mut rng);
206 
207             // fill the buf with a prefix
208             for _ in 0..prefix_len {
209                 prefix.push(rng.gen());
210             }
211 
212             decoded_with_prefix.resize(prefix_len, 0);
213             decoded_with_prefix.copy_from_slice(&prefix);
214 
215             // decode into the non-empty buf
216             engine
217                 .decode_vec(&encoded_data, &mut decoded_with_prefix)
218                 .unwrap();
219             // also decode into the empty buf
220             engine
221                 .decode_vec(&encoded_data, &mut decoded_without_prefix)
222                 .unwrap();
223 
224             assert_eq!(
225                 prefix_len + decoded_without_prefix.len(),
226                 decoded_with_prefix.len()
227             );
228             assert_eq!(orig_data, decoded_without_prefix);
229 
230             // append plain decode onto prefix
231             prefix.append(&mut decoded_without_prefix);
232 
233             assert_eq!(prefix, decoded_with_prefix);
234         }
235     }
236 
237     #[test]
decode_slice_doesnt_clobber_existing_prefix_or_suffix()238     fn decode_slice_doesnt_clobber_existing_prefix_or_suffix() {
239         do_decode_slice_doesnt_clobber_existing_prefix_or_suffix(|e, input, output| {
240             e.decode_slice(input, output).unwrap()
241         })
242     }
243 
244     #[test]
decode_slice_unchecked_doesnt_clobber_existing_prefix_or_suffix()245     fn decode_slice_unchecked_doesnt_clobber_existing_prefix_or_suffix() {
246         do_decode_slice_doesnt_clobber_existing_prefix_or_suffix(|e, input, output| {
247             e.decode_slice_unchecked(input, output).unwrap()
248         })
249     }
250 
251     #[test]
decode_engine_estimation_works_for_various_lengths()252     fn decode_engine_estimation_works_for_various_lengths() {
253         let engine = GeneralPurpose::new(&alphabet::STANDARD, general_purpose::NO_PAD);
254         for num_prefix_quads in 0..100 {
255             for suffix in &["AA", "AAA", "AAAA"] {
256                 let mut prefix = "AAAA".repeat(num_prefix_quads);
257                 prefix.push_str(suffix);
258                 // make sure no overflow (and thus a panic) occurs
259                 let res = engine.decode(prefix);
260                 assert!(res.is_ok());
261             }
262         }
263     }
264 
265     #[test]
decode_slice_output_length_errors()266     fn decode_slice_output_length_errors() {
267         for num_quads in 1..100 {
268             let input = "AAAA".repeat(num_quads);
269             let mut vec = vec![0; (num_quads - 1) * 3];
270             assert_eq!(
271                 DecodeSliceError::OutputSliceTooSmall,
272                 STANDARD.decode_slice(&input, &mut vec).unwrap_err()
273             );
274             vec.push(0);
275             assert_eq!(
276                 DecodeSliceError::OutputSliceTooSmall,
277                 STANDARD.decode_slice(&input, &mut vec).unwrap_err()
278             );
279             vec.push(0);
280             assert_eq!(
281                 DecodeSliceError::OutputSliceTooSmall,
282                 STANDARD.decode_slice(&input, &mut vec).unwrap_err()
283             );
284             vec.push(0);
285             // now it works
286             assert_eq!(
287                 num_quads * 3,
288                 STANDARD.decode_slice(&input, &mut vec).unwrap()
289             );
290         }
291     }
292 
do_decode_slice_doesnt_clobber_existing_prefix_or_suffix< F: Fn(&GeneralPurpose, &[u8], &mut [u8]) -> usize, >( call_decode: F, )293     fn do_decode_slice_doesnt_clobber_existing_prefix_or_suffix<
294         F: Fn(&GeneralPurpose, &[u8], &mut [u8]) -> usize,
295     >(
296         call_decode: F,
297     ) {
298         let mut orig_data = Vec::new();
299         let mut encoded_data = String::new();
300         let mut decode_buf = Vec::new();
301         let mut decode_buf_copy: Vec<u8> = Vec::new();
302 
303         let input_len_range = Uniform::new(0, 1000);
304 
305         let mut rng = rand::rngs::SmallRng::from_entropy();
306 
307         for _ in 0..10_000 {
308             orig_data.clear();
309             encoded_data.clear();
310             decode_buf.clear();
311             decode_buf_copy.clear();
312 
313             let input_len = input_len_range.sample(&mut rng);
314 
315             for _ in 0..input_len {
316                 orig_data.push(rng.gen());
317             }
318 
319             let engine = random_engine(&mut rng);
320             engine.encode_string(&orig_data, &mut encoded_data);
321             assert_encode_sanity(&encoded_data, engine.config().encode_padding(), input_len);
322 
323             // fill the buffer with random garbage, long enough to have some room before and after
324             for _ in 0..5000 {
325                 decode_buf.push(rng.gen());
326             }
327 
328             // keep a copy for later comparison
329             decode_buf_copy.extend(decode_buf.iter());
330 
331             let offset = 1000;
332 
333             // decode into the non-empty buf
334             let decode_bytes_written =
335                 call_decode(&engine, encoded_data.as_bytes(), &mut decode_buf[offset..]);
336 
337             assert_eq!(orig_data.len(), decode_bytes_written);
338             assert_eq!(
339                 orig_data,
340                 &decode_buf[offset..(offset + decode_bytes_written)]
341             );
342             assert_eq!(&decode_buf_copy[0..offset], &decode_buf[0..offset]);
343             assert_eq!(
344                 &decode_buf_copy[offset + decode_bytes_written..],
345                 &decode_buf[offset + decode_bytes_written..]
346             );
347         }
348     }
349 }
350