diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/web/Cargo.toml | 2 | ||||
-rw-r--r-- | ext/web/lib.rs | 69 |
2 files changed, 19 insertions, 52 deletions
diff --git a/ext/web/Cargo.toml b/ext/web/Cargo.toml index ada3faab6..e321f4fb6 100644 --- a/ext/web/Cargo.toml +++ b/ext/web/Cargo.toml @@ -15,7 +15,7 @@ path = "lib.rs" [dependencies] async-trait = "0.1.51" -base64 = "0.13.0" +base64-simd = "0.6.2" deno_core = { version = "0.140.0", path = "../../core" } encoding_rs = "0.8.31" flate2 = "1" diff --git a/ext/web/lib.rs b/ext/web/lib.rs index b21ea3812..9bc7c1cce 100644 --- a/ext/web/lib.rs +++ b/ext/web/lib.rs @@ -124,74 +124,41 @@ pub fn init<P: TimersPermission + 'static>( #[op] fn op_base64_decode(input: String) -> Result<ZeroCopyBuf, AnyError> { - let mut input = input.into_bytes(); - input.retain(|c| !c.is_ascii_whitespace()); - Ok(b64_decode(&input)?.into()) + Ok(forgiving_base64_decode(input.into_bytes())?.into()) } #[op] -fn op_base64_atob(mut s: ByteString) -> Result<ByteString, AnyError> { - s.retain(|c| !c.is_ascii_whitespace()); - - // If padding is expected, fail if not 4-byte aligned - if s.len() % 4 != 0 && (s.ends_with(b"==") || s.ends_with(b"=")) { - return Err( - DomExceptionInvalidCharacterError::new("Failed to decode base64.").into(), - ); - } - - Ok(b64_decode(&s)?.into()) +fn op_base64_atob(s: ByteString) -> Result<ByteString, AnyError> { + Ok(forgiving_base64_decode(s.into())?.into()) } -fn b64_decode(input: &[u8]) -> Result<Vec<u8>, AnyError> { - // "If the length of input divides by 4 leaving no remainder, then: - // if input ends with one or two U+003D EQUALS SIGN (=) characters, - // remove them from input." - let input = match input.len() % 4 == 0 { - true if input.ends_with(b"==") => &input[..input.len() - 2], - true if input.ends_with(b"=") => &input[..input.len() - 1], - _ => input, - }; +/// See <https://infra.spec.whatwg.org/#forgiving-base64> +fn forgiving_base64_decode(mut input: Vec<u8>) -> Result<Vec<u8>, AnyError> { + let error: _ = + || DomExceptionInvalidCharacterError::new("Failed to decode base64"); - // "If the length of input divides by 4 leaving a remainder of 1, - // throw an InvalidCharacterError exception and abort these steps." - if input.len() % 4 == 1 { - return Err( - DomExceptionInvalidCharacterError::new("Failed to decode base64.").into(), - ); - } - - let cfg = base64::Config::new(base64::CharacterSet::Standard, true) - .decode_allow_trailing_bits(true); - let out = base64::decode_config(input, cfg).map_err(|err| match err { - base64::DecodeError::InvalidByte(_, _) => { - DomExceptionInvalidCharacterError::new( - "Failed to decode base64: invalid character", - ) - } - _ => DomExceptionInvalidCharacterError::new(&format!( - "Failed to decode base64: {:?}", - err - )), - })?; + let decoded = base64_simd::Base64::forgiving_decode_inplace(&mut input) + .map_err(|_| error())?; - Ok(out) + let decoded_len = decoded.len(); + input.truncate(decoded_len); + Ok(input) } #[op] fn op_base64_encode(s: ZeroCopyBuf) -> String { - b64_encode(&s) + forgiving_base64_encode(s.as_ref()) } #[op] fn op_base64_btoa(s: ByteString) -> String { - b64_encode(s) + forgiving_base64_encode(s.as_ref()) } -fn b64_encode(s: impl AsRef<[u8]>) -> String { - let cfg = base64::Config::new(base64::CharacterSet::Standard, true) - .decode_allow_trailing_bits(true); - base64::encode_config(s.as_ref(), cfg) +/// See <https://infra.spec.whatwg.org/#forgiving-base64> +fn forgiving_base64_encode(s: &[u8]) -> String { + let base64 = base64_simd::Base64::STANDARD; + base64.encode_to_boxed_str(s).into_string() } #[derive(Deserialize)] |