From 10f29fbb2670cb3461dd8383da851fb909c63027 Mon Sep 17 00:00:00 2001 From: Finn Bear Date: Fri, 12 May 2023 16:55:52 -0700 Subject: [PATCH] Bugfix - error on integer overflow in SurrealQL. (#1983) --- lib/src/err/mod.rs | 10 +++++----- lib/src/sql/value/value.rs | 30 ++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/lib/src/err/mod.rs b/lib/src/err/mod.rs index cf3ce91f..22b81ab1 100644 --- a/lib/src/err/mod.rs +++ b/lib/src/err/mod.rs @@ -347,23 +347,23 @@ pub enum Error { into: Cow<'static, str>, }, - /// The requested function does not exist + /// Cannot perform addition #[error("Cannot perform addition with '{0}' and '{1}'")] TryAdd(String, String), - /// The requested function does not exist + /// Cannot perform subtraction #[error("Cannot perform subtraction with '{0}' and '{1}'")] TrySub(String, String), - /// The requested function does not exist + /// Cannot perform multiplication #[error("Cannot perform multiplication with '{0}' and '{1}'")] TryMul(String, String), - /// The requested function does not exist + /// Cannot perform division #[error("Cannot perform division with '{0}' and '{1}'")] TryDiv(String, String), - /// The requested function does not exist + /// Cannot perform power #[error("Cannot raise the value '{0}' with '{1}'")] TryPow(String, String), diff --git a/lib/src/sql/value/value.rs b/lib/src/sql/value/value.rs index 8872a455..24599f31 100644 --- a/lib/src/sql/value/value.rs +++ b/lib/src/sql/value/value.rs @@ -2003,7 +2003,12 @@ impl TryAdd for Value { type Output = Self; fn try_add(self, other: Self) -> Result { match (self, other) { - (Value::Number(v), Value::Number(w)) => Ok(Value::Number(v + w)), + (Value::Number(v), Value::Number(w)) => match (v, w) { + (Number::Int(v), Number::Int(w)) if v.checked_add(w).is_none() => { + Err(Error::TryAdd(v.to_string(), w.to_string())) + } + (v, w) => Ok(Value::Number(v + w)), + }, (Value::Strand(v), Value::Strand(w)) => Ok(Value::Strand(v + w)), (Value::Datetime(v), Value::Duration(w)) => Ok(Value::Datetime(w + v)), (Value::Duration(v), Value::Datetime(w)) => Ok(Value::Datetime(v + w)), @@ -2024,7 +2029,12 @@ impl TrySub for Value { type Output = Self; fn try_sub(self, other: Self) -> Result { match (self, other) { - (Value::Number(v), Value::Number(w)) => Ok(Value::Number(v - w)), + (Value::Number(v), Value::Number(w)) => match (v, w) { + (Number::Int(v), Number::Int(w)) if v.checked_sub(w).is_none() => { + Err(Error::TrySub(v.to_string(), w.to_string())) + } + (v, w) => Ok(Value::Number(v - w)), + }, (Value::Datetime(v), Value::Datetime(w)) => Ok(Value::Duration(v - w)), (Value::Datetime(v), Value::Duration(w)) => Ok(Value::Datetime(w - v)), (Value::Duration(v), Value::Datetime(w)) => Ok(Value::Datetime(v - w)), @@ -2045,7 +2055,12 @@ impl TryMul for Value { type Output = Self; fn try_mul(self, other: Self) -> Result { match (self, other) { - (Value::Number(v), Value::Number(w)) => Ok(Value::Number(v * w)), + (Value::Number(v), Value::Number(w)) => match (v, w) { + (Number::Int(v), Number::Int(w)) if v.checked_mul(w).is_none() => { + Err(Error::TryMul(v.to_string(), w.to_string())) + } + (v, w) => Ok(Value::Number(v * w)), + }, (v, w) => Err(Error::TryMul(v.to_raw_string(), w.to_raw_string())), } } @@ -2082,7 +2097,14 @@ impl TryPow for Value { type Output = Self; fn try_pow(self, other: Self) -> Result { match (self, other) { - (Value::Number(v), Value::Number(w)) => Ok(Value::Number(v.pow(w))), + (Value::Number(v), Value::Number(w)) => match (v, w) { + (Number::Int(v), Number::Int(w)) + if w.try_into().ok().and_then(|w| v.checked_pow(w)).is_none() => + { + Err(Error::TryPow(v.to_string(), w.to_string())) + } + (v, w) => Ok(Value::Number(v.pow(w))), + }, (v, w) => Err(Error::TryPow(v.to_raw_string(), w.to_raw_string())), } }