From 4524d4034fbe3c38e95d0435f1fa6582ff59ae01 Mon Sep 17 00:00:00 2001 From: itchyny Date: Sat, 2 Mar 2024 11:25:41 +0900 Subject: [PATCH] Fix implode/0 to emit replacement characters on invalid input numbers --- src/intrinsic/string.rs | 12 ++++-------- src/vm/error.rs | 2 -- tests/from_manual/functions.rs | 13 +++++++++++++ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/intrinsic/string.rs b/src/intrinsic/string.rs index 2311bd8..6f99b18 100644 --- a/src/intrinsic/string.rs +++ b/src/intrinsic/string.rs @@ -81,14 +81,10 @@ pub(crate) fn implode(value: Value) -> Result { let s = s .iter() .map(|c| match c { - Value::Number(c) => { - let c = c - .to_u32() - .ok_or(QueryExecutionError::InvalidNumberAsChar(*c))?; - let c = char::try_from(c) - .map_err(|_| QueryExecutionError::InvalidNumberAsChar(c.into()))?; - Ok(c) - } + Value::Number(c) => Ok(c + .to_u32() + .and_then(|c| char::try_from(c).ok()) + .unwrap_or(char::REPLACEMENT_CHARACTER)), _ => Err(QueryExecutionError::InvalidArgType("implode", c.clone())), }) .collect::>()?; diff --git a/src/vm/error.rs b/src/vm/error.rs index 2f66784..d9ed5af 100644 --- a/src/vm/error.rs +++ b/src/vm/error.rs @@ -62,8 +62,6 @@ pub enum QueryExecutionError { InvalidAsBase64(#[from] base64::DecodeError), #[error("Invalid as a UTF-8-encoded byte array")] InvalidUTF8Bytes(#[from] std::string::FromUtf8Error), - #[error("Invalid as a unicode scalar value `{0:}`")] - InvalidNumberAsChar(Number), #[error("utf8bytelength is applied to non-string value`{0:?}`")] InvalidUTF8ByteLength(Value), #[error("{0:?} was called invalidly with arg `{1:?}`")] diff --git a/tests/from_manual/functions.rs b/tests/from_manual/functions.rs index 37a2f19..4485f91 100644 --- a/tests/from_manual/functions.rs +++ b/tests/from_manual/functions.rs @@ -1190,6 +1190,19 @@ test!( "# ); +test!( + implode2, + r#" + implode + "#, + r#" + [-1, 0, 1, 1114111, 1114112] + "#, + r#" + "\ufffd\u0000\u0001\udbff\udfff\ufffd" + "# +); + test!( split1, r#"