From 902c09c52c8515bfa21ceb3968fd367ec66239cf Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 08:57:36 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20CodeRabbit=20Chat:=20Enforce=20N?= =?UTF-8?q?umeric=20Type=20Validation=20for=20Power=20and=20Trigonometric?= =?UTF-8?q?=20Opcodes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../instructions/math/arithmetic/cos_func.rs | 26 +++++++++- .../instructions/math/arithmetic/pow_func.rs | 42 +++++++++++++--- .../instructions/math/arithmetic/powf_func.rs | 42 ++++++++++++++-- .../instructions/math/arithmetic/powi_func.rs | 50 ++++++++++++++++--- .../instructions/math/arithmetic/sin_func.rs | 26 +++++++++- .../instructions/math/arithmetic/tan_func.rs | 26 +++++++++- 6 files changed, 191 insertions(+), 21 deletions(-) diff --git a/rust/src/instructions/math/arithmetic/cos_func.rs b/rust/src/instructions/math/arithmetic/cos_func.rs index 9b5a92e4..8091b2fd 100644 --- a/rust/src/instructions/math/arithmetic/cos_func.rs +++ b/rust/src/instructions/math/arithmetic/cos_func.rs @@ -19,7 +19,12 @@ use crate::types::value::Value; use crate::utils::{expected_type::expected_type, get_type_name::get_type_name}; #[inline(always)] pub fn cos_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result { - if !a.is_number() { + if !matches!( + (&a, num_type), + (Value::Float16(_), PrimitiveTypes::Hlf) + | (Value::Float32(_), PrimitiveTypes::Flt) + | (Value::Float64(_), PrimitiveTypes::Dbl) + ) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), @@ -75,4 +80,23 @@ mod tests { )); assert_eq!(stack, original); } + #[test] + fn rejects_integer_and_mismatched_float_operands_without_mutating_stack() { + for (operand, found) in [ + (Value::Int32(1), "Unknown"), + (Value::Float64(1.0), "Double"), + ] { + assert!(matches!( + cos_values(operand.clone(), PrimitiveTypes::Flt, 19), + Err(VMError::TypeMismatch { ip: 19, expected: "Float", found: actual }) if actual == found + )); + let mut stack = Stack::from_vec(vec![operand]); + let original = stack.clone(); + assert!(matches!( + cos_func(&mut stack, PrimitiveTypes::Flt, 20), + Err(VMError::TypeMismatch { ip: 20, expected: "Float", found: actual }) if actual == found + )); + assert_eq!(stack, original); + } + } } diff --git a/rust/src/instructions/math/arithmetic/pow_func.rs b/rust/src/instructions/math/arithmetic/pow_func.rs index d7132174..0c46cff8 100644 --- a/rust/src/instructions/math/arithmetic/pow_func.rs +++ b/rust/src/instructions/math/arithmetic/pow_func.rs @@ -90,19 +90,47 @@ mod tests { use super::*; #[test] fn integer_directive_rejects_float_operands_without_mutating_stack() { - for (a, b, found) in [ - (Value::Float32(1.0), Value::Int32(2), "Float"), - (Value::Int32(1), Value::Float64(2.0), "Double"), + for (num_type, a, b, expected, found) in [ + ( + PrimitiveTypes::Sht, + Value::Float16(half::f16::ONE), + Value::Int16(2), + "Short", + "Half", + ), + ( + PrimitiveTypes::Int, + Value::Float32(1.0), + Value::Int32(2), + "Integer", + "Float", + ), + ( + PrimitiveTypes::Lng, + Value::Int64(1), + Value::Float64(2.0), + "Long", + "Double", + ), + ( + PrimitiveTypes::Oct, + Value::Float32(1.0), + Value::Int128(2), + "Octa", + "Float", + ), ] { assert!(matches!( - pow_values(a.clone(), b.clone(), PrimitiveTypes::Int, 8), - Err(VMError::TypeMismatch { ip: 8, expected: "Integer", found: actual }) if actual == found + pow_values(a.clone(), b.clone(), num_type, 8), + Err(VMError::TypeMismatch { ip: 8, expected: actual_expected, found: actual_found }) + if actual_expected == expected && actual_found == found )); let mut stack = Stack::from_vec(vec![a, b]); let original = stack.clone(); assert!(matches!( - pow_func(&mut stack, PrimitiveTypes::Int, 9), - Err(VMError::TypeMismatch { ip: 9, expected: "Integer", found: actual }) if actual == found + pow_func(&mut stack, num_type, 9), + Err(VMError::TypeMismatch { ip: 9, expected: actual_expected, found: actual_found }) + if actual_expected == expected && actual_found == found )); assert_eq!(stack, original); } diff --git a/rust/src/instructions/math/arithmetic/powf_func.rs b/rust/src/instructions/math/arithmetic/powf_func.rs index da64e7b2..1880c206 100644 --- a/rust/src/instructions/math/arithmetic/powf_func.rs +++ b/rust/src/instructions/math/arithmetic/powf_func.rs @@ -24,14 +24,22 @@ pub fn powf_values( num_type: PrimitiveTypes, ip: usize, ) -> Result { - if !a.is_number() { + let matches_directive = |value: &Value| { + matches!( + (value, num_type), + (Value::Float16(_), PrimitiveTypes::Hlf) + | (Value::Float32(_), PrimitiveTypes::Flt) + | (Value::Float64(_), PrimitiveTypes::Dbl) + ) + }; + if !matches_directive(&a) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), found: get_type_name(a), }); } - if !b.is_number() { + if !matches_directive(&b) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), @@ -46,7 +54,7 @@ pub fn powf_values( return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), - found: a.type_of(), + found: get_type_name(a), }); } }) @@ -82,14 +90,19 @@ mod tests { }) )); assert!(matches!( - powf_values(Value::Int32(1), invalid.clone(), PrimitiveTypes::Flt, 18), + powf_values( + Value::Float32(1.0), + invalid.clone(), + PrimitiveTypes::Flt, + 18 + ), Err(VMError::TypeMismatch { ip: 18, expected: "Float", found: "String" }) )); - let mut stack = Stack::from_vec(vec![Value::Int32(1), invalid]); + let mut stack = Stack::from_vec(vec![Value::Float32(1.0), invalid]); let original = stack.clone(); assert!(matches!( powf_func(&mut stack, PrimitiveTypes::Flt, 19), @@ -101,4 +114,23 @@ mod tests { )); assert_eq!(stack, original); } + #[test] + fn rejects_integer_and_mismatched_float_operands_without_mutating_stack() { + for (a, b, found) in [ + (Value::Int32(2), Value::Float32(3.0), "Unknown"), + (Value::Float32(2.0), Value::Float64(3.0), "Double"), + ] { + assert!(matches!( + powf_values(a.clone(), b.clone(), PrimitiveTypes::Flt, 20), + Err(VMError::TypeMismatch { ip: 20, expected: "Float", found: actual }) if actual == found + )); + let mut stack = Stack::from_vec(vec![a, b]); + let original = stack.clone(); + assert!(matches!( + powf_func(&mut stack, PrimitiveTypes::Flt, 21), + Err(VMError::TypeMismatch { ip: 21, expected: "Float", found: actual }) if actual == found + )); + assert_eq!(stack, original); + } + } } diff --git a/rust/src/instructions/math/arithmetic/powi_func.rs b/rust/src/instructions/math/arithmetic/powi_func.rs index 475a33cc..d812922d 100644 --- a/rust/src/instructions/math/arithmetic/powi_func.rs +++ b/rust/src/instructions/math/arithmetic/powi_func.rs @@ -31,14 +31,26 @@ pub fn powi_values( num_type: PrimitiveTypes, ip: usize, ) -> Result { - if !a.is_number() { + let valid_base = matches!( + (&a, num_type), + (Value::Float16(_), PrimitiveTypes::Hlf) + | (Value::Float32(_), PrimitiveTypes::Flt) + | (Value::Float64(_), PrimitiveTypes::Dbl) + ); + let valid_exponent = matches!( + (&b, num_type), + (Value::Int16(_), PrimitiveTypes::Hlf) + | (Value::Int32(_), PrimitiveTypes::Flt) + | (Value::Int64(_), PrimitiveTypes::Dbl) + ); + if !valid_base { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type), found: get_type_name(a), }); } - if !b.is_number() { + if !valid_exponent { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type), @@ -53,7 +65,7 @@ pub fn powi_values( return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type), - found: a.type_of(), + found: get_type_name(a), }); } }) @@ -89,14 +101,19 @@ mod tests { }) )); assert!(matches!( - powi_values(Value::Int32(1), invalid.clone(), PrimitiveTypes::Flt, 18), + powi_values( + Value::Float32(1.0), + invalid.clone(), + PrimitiveTypes::Flt, + 18 + ), Err(VMError::TypeMismatch { ip: 18, expected: "Float32/Int32", found: "String" }) )); - let mut stack = Stack::from_vec(vec![Value::Int32(1), invalid]); + let mut stack = Stack::from_vec(vec![Value::Float32(1.0), invalid]); let original = stack.clone(); assert!(matches!( powi_func(&mut stack, PrimitiveTypes::Flt, 19), @@ -109,6 +126,27 @@ mod tests { assert_eq!(stack, original); } #[test] + fn rejects_mismatched_base_and_float_exponent_without_mutating_stack() { + for (a, b, found) in [ + (Value::Float64(2.0), Value::Int32(3), "Double"), + (Value::Float32(2.0), Value::Float32(3.0), "Float"), + ] { + assert!(matches!( + powi_values(a.clone(), b.clone(), PrimitiveTypes::Flt, 23), + Err(VMError::TypeMismatch { ip: 23, expected: "Float32/Int32", found: actual }) + if actual == found + )); + let mut stack = Stack::from_vec(vec![a, b]); + let original = stack.clone(); + assert!(matches!( + powi_func(&mut stack, PrimitiveTypes::Flt, 24), + Err(VMError::TypeMismatch { ip: 24, expected: "Float32/Int32", found: actual }) + if actual == found + )); + assert_eq!(stack, original); + } + } + #[test] fn invalid_operands_report_directive_specific_expected_types() { let invalid = Value::String("invalid".into()); assert!(matches!( @@ -140,7 +178,7 @@ mod tests { Err(VMError::TypeMismatch { ip: 22, expected: "Float32/Int32", - found: "float64" + found: "Double" }) )); } diff --git a/rust/src/instructions/math/arithmetic/sin_func.rs b/rust/src/instructions/math/arithmetic/sin_func.rs index f872118a..ac760bc1 100644 --- a/rust/src/instructions/math/arithmetic/sin_func.rs +++ b/rust/src/instructions/math/arithmetic/sin_func.rs @@ -19,7 +19,12 @@ use crate::types::value::Value; use crate::utils::{expected_type::expected_type, get_type_name::get_type_name}; #[inline(always)] pub fn sin_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result { - if !a.is_number() { + if !matches!( + (&a, num_type), + (Value::Float16(_), PrimitiveTypes::Hlf) + | (Value::Float32(_), PrimitiveTypes::Flt) + | (Value::Float64(_), PrimitiveTypes::Dbl) + ) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), @@ -75,4 +80,23 @@ mod tests { )); assert_eq!(stack, original); } + #[test] + fn rejects_integer_and_mismatched_float_operands_without_mutating_stack() { + for (operand, found) in [ + (Value::Int32(1), "Unknown"), + (Value::Float64(1.0), "Double"), + ] { + assert!(matches!( + sin_values(operand.clone(), PrimitiveTypes::Flt, 19), + Err(VMError::TypeMismatch { ip: 19, expected: "Float", found: actual }) if actual == found + )); + let mut stack = Stack::from_vec(vec![operand]); + let original = stack.clone(); + assert!(matches!( + sin_func(&mut stack, PrimitiveTypes::Flt, 20), + Err(VMError::TypeMismatch { ip: 20, expected: "Float", found: actual }) if actual == found + )); + assert_eq!(stack, original); + } + } } diff --git a/rust/src/instructions/math/arithmetic/tan_func.rs b/rust/src/instructions/math/arithmetic/tan_func.rs index e48a8a72..cd711fe8 100644 --- a/rust/src/instructions/math/arithmetic/tan_func.rs +++ b/rust/src/instructions/math/arithmetic/tan_func.rs @@ -19,7 +19,12 @@ use crate::types::value::Value; use crate::utils::{expected_type::expected_type, get_type_name::get_type_name}; #[inline(always)] pub fn tan_values(a: Value, num_type: PrimitiveTypes, ip: usize) -> Result { - if !a.is_number() { + if !matches!( + (&a, num_type), + (Value::Float16(_), PrimitiveTypes::Hlf) + | (Value::Float32(_), PrimitiveTypes::Flt) + | (Value::Float64(_), PrimitiveTypes::Dbl) + ) { return Err(VMError::TypeMismatch { ip, expected: expected_type(num_type, ExpectedCategory::Float), @@ -75,4 +80,23 @@ mod tests { )); assert_eq!(stack, original); } + #[test] + fn rejects_integer_and_mismatched_float_operands_without_mutating_stack() { + for (operand, found) in [ + (Value::Int32(1), "Unknown"), + (Value::Float64(1.0), "Double"), + ] { + assert!(matches!( + tan_values(operand.clone(), PrimitiveTypes::Flt, 19), + Err(VMError::TypeMismatch { ip: 19, expected: "Float", found: actual }) if actual == found + )); + let mut stack = Stack::from_vec(vec![operand]); + let original = stack.clone(); + assert!(matches!( + tan_func(&mut stack, PrimitiveTypes::Flt, 20), + Err(VMError::TypeMismatch { ip: 20, expected: "Float", found: actual }) if actual == found + )); + assert_eq!(stack, original); + } + } }