diff --git a/tower-sessions-core/src/session.rs b/tower-sessions-core/src/session.rs index c6b95cd..db04d7a 100644 --- a/tower-sessions-core/src/session.rs +++ b/tower-sessions-core/src/session.rs @@ -4,13 +4,14 @@ use std::{ fmt::{self, Display}, hash::Hash, result, - str::FromStr, + str::{self, FromStr}, sync::{ atomic::{self, AtomicBool}, Arc, }, }; +use base64::{engine::general_purpose::URL_SAFE_NO_PAD, DecodeError, Engine as _}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::Value; use time::{Duration, OffsetDateTime}; @@ -870,42 +871,31 @@ impl Default for Id { impl Display for Id { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _}; - - let mut encoded = [0u8; 22]; + let mut encoded = [0; 22]; URL_SAFE_NO_PAD .encode_slice(self.0.to_le_bytes(), &mut encoded) .expect("Encoded ID must be exactly 22 bytes"); - let encoded = std::str::from_utf8(&encoded).expect("Encoded ID must be valid UTF-8"); + let encoded = str::from_utf8(&encoded).expect("Encoded ID must be valid UTF-8"); f.write_str(encoded) } } impl FromStr for Id { - type Err = IdError; + type Err = base64::DecodeSliceError; fn from_str(s: &str) -> result::Result { - use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _}; - - let mut decoded = [0u8; 22]; - URL_SAFE_NO_PAD.decode_slice(s.as_bytes(), &mut decoded)?; - // N.B. The last six bytes will be zeroes. - let id_bytes: [u8; 16] = decoded[..16].try_into().map_err(|_| Self::Err::Length)?; + let mut decoded = [0; 16]; + let bytes_decoded = URL_SAFE_NO_PAD.decode_slice(s.as_bytes(), &mut decoded)?; + if bytes_decoded != 16 { + let err = DecodeError::InvalidLength(bytes_decoded); + return Err(base64::DecodeSliceError::DecodeError(err)); + } - Ok(Self(i128::from_le_bytes(id_bytes))) + Ok(Self(i128::from_le_bytes(decoded))) } } -#[derive(Debug, thiserror::Error)] -pub enum IdError { - #[error(transparent)] - DecodeSlice(#[from] base64::DecodeSliceError), - - #[error("Provided base64 string is not composed of exactly 128-bytes")] - Length, -} - /// Record type that's appropriate for encoding and decoding sessions to and /// from session stores. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]