From d6594866aaf30b609cb2e61175d003c90cf012a5 Mon Sep 17 00:00:00 2001 From: Daniel Treiman Date: Mon, 10 Jun 2024 18:08:14 -0700 Subject: [PATCH 1/3] Base64 decoding accepts standard or url-safe. --- google-apis-common/src/serde.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/google-apis-common/src/serde.rs b/google-apis-common/src/serde.rs index 622a60a215..84be4a2a28 100644 --- a/google-apis-common/src/serde.rs +++ b/google-apis-common/src/serde.rs @@ -170,7 +170,13 @@ pub mod standard_base64 { D: Deserializer<'de>, { let s: Cow = Deserialize::deserialize(deserializer)?; - base64::prelude::BASE64_STANDARD.decode(s.as_ref()).map_err(serde::de::Error::custom) + match base64::prelude::BASE64_STANDARD.decode(s.as_ref()) { + Ok(decoded) => Ok(decoded), + Err(first_err) => match general_purpose::URL_SAFE.decode(s.as_ref()) { + Ok(decoded) => Ok(decoded), + Err(_) => Err(serde::de::Error::custom(first_err)) + } + } } } } @@ -202,7 +208,13 @@ pub mod urlsafe_base64 { D: Deserializer<'de>, { let s: Cow = Deserialize::deserialize(deserializer)?; - base64::prelude::BASE64_URL_SAFE.decode(s.as_ref()).map_err(serde::de::Error::custom) + match base64::prelude::URL_SAFE.decode(s.as_ref()) { + Ok(decoded) => Ok(decoded), + Err(first_err) => match general_purpose::URL_STANDARD.decode(s.as_ref()) { + Ok(decoded) => Ok(decoded), + Err(_) => Err(serde::de::Error::custom(first_err)) + } + } } } } From 74b4a08e7cc464efa3cf72c9e67533d397d54086 Mon Sep 17 00:00:00 2001 From: Daniel Treiman Date: Mon, 10 Jun 2024 18:11:45 -0700 Subject: [PATCH 2/3] Fix copy-paste mistakes. --- google-apis-common/src/serde.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/google-apis-common/src/serde.rs b/google-apis-common/src/serde.rs index 84be4a2a28..be62bf5ad7 100644 --- a/google-apis-common/src/serde.rs +++ b/google-apis-common/src/serde.rs @@ -172,7 +172,7 @@ pub mod standard_base64 { let s: Cow = Deserialize::deserialize(deserializer)?; match base64::prelude::BASE64_STANDARD.decode(s.as_ref()) { Ok(decoded) => Ok(decoded), - Err(first_err) => match general_purpose::URL_SAFE.decode(s.as_ref()) { + Err(first_err) => match base64::prelude::BASE64_URL_SAFE.decode(s.as_ref()) { Ok(decoded) => Ok(decoded), Err(_) => Err(serde::de::Error::custom(first_err)) } @@ -208,9 +208,9 @@ pub mod urlsafe_base64 { D: Deserializer<'de>, { let s: Cow = Deserialize::deserialize(deserializer)?; - match base64::prelude::URL_SAFE.decode(s.as_ref()) { + match base64::prelude::BASE64_URL_SAFE.decode(s.as_ref()) { Ok(decoded) => Ok(decoded), - Err(first_err) => match general_purpose::URL_STANDARD.decode(s.as_ref()) { + Err(first_err) => match base64::prelude::BASE64_STANDARD.decode(s.as_ref()) { Ok(decoded) => Ok(decoded), Err(_) => Err(serde::de::Error::custom(first_err)) } From b5bc9d694185d10ae365f886545506954bdef198 Mon Sep 17 00:00:00 2001 From: Daniel Treiman Date: Tue, 11 Jun 2024 09:12:37 -0700 Subject: [PATCH 3/3] Test to ensure standard decoder accepts urlsafe, and vice-versa --- google-apis-common/src/serde.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/google-apis-common/src/serde.rs b/google-apis-common/src/serde.rs index be62bf5ad7..8d95afe87c 100644 --- a/google-apis-common/src/serde.rs +++ b/google-apis-common/src/serde.rs @@ -355,14 +355,28 @@ mod test { assert_eq!(Some(b"hello world".as_slice()), wrapper.bytes.as_deref()); } + #[test] + fn urlsafe_base64_de_standard_success_cases() { + let wrapper: Base64URLSafeWrapper = // Expect URL-safe base64 accepts standard encoding + serde_json::from_reader(r#"{"bytes": "REE/P0V+Nz4oIWtH"}"#.as_bytes()).unwrap(); + assert_eq!(Some(b"DA??E~7>(!kG".as_slice()), wrapper.bytes.as_deref()); + } + #[test] fn urlsafe_base64_de_failure_cases() { assert!( - serde_json::from_str::(r#"{"bytes": "aGVsbG8gd29ybG+Q"}"#) + serde_json::from_str::(r#"{"bytes": "aGVsbG8gd29ybG&Q"}"#) .is_err() ); } + #[test] + fn standard_base64_de_urlsafe_success_cases() { + let wrapper: Base64URLSafeWrapper = // Expect standard base64 accepts url-safe encoding + serde_json::from_reader(r#"{"bytes": "REE_P0V-Nz4oIWtH"}"#.as_bytes()).unwrap(); + assert_eq!(Some(b"DA??E~7>(!kG".as_slice()), wrapper.bytes.as_deref()); + } + #[test] fn standard_base64_de_failure_cases() { assert!(serde_json::from_str::(r#"{"bytes": "%"}"#).is_err());