From cae738223e9357e26299f0f66607478441ae0147 Mon Sep 17 00:00:00 2001 From: rulego-team Date: Tue, 7 Jul 2026 14:44:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20trunc/pow/exp=20=E9=9D=9E=E6=B3=95?= =?UTF-8?q?=E5=85=A5=E5=8F=82=E4=B8=8E=E8=B6=8A=E7=95=8C=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E9=94=99=E8=AF=AF=EF=BC=8C=E4=B8=8D=E5=86=8D=E9=9D=99=E9=BB=98?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=20NaN/0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions/functions_conversion.go | 17 +++++++++++++---- functions/functions_conversion_test.go | 18 ++++++++++++++++++ functions/functions_math.go | 12 ++++++++++-- functions/functions_math_test.go | 21 +++++++++++++++++++++ 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/functions/functions_conversion.go b/functions/functions_conversion.go index 1243391..05642bd 100644 --- a/functions/functions_conversion.go +++ b/functions/functions_conversion.go @@ -448,19 +448,28 @@ func (f *TruncFunction) Execute(ctx *FunctionContext, args []interface{}) (inter return nil, err } - // 转换第一个参数为浮点数 - num := cast.ToFloat64(args[0]) + // 转换第一个参数为浮点数(NULL/非数值返回错误,不再静默当 0) + num, err := cast.ToFloat64E(args[0]) + if err != nil { + return nil, err + } // 转换第二个参数为整数(精度) - precision := cast.ToInt(args[1]) + precision, err := cast.ToIntE(args[1]) + if err != nil { + return nil, err + } // 精度不能为负数 if precision < 0 { return nil, fmt.Errorf("trunc precision cannot be negative") } - // 计算截断 + // 计算截断。precision 过大时 multiplier 溢出为 +Inf,截断无意义,报错。 multiplier := math.Pow(10, float64(precision)) + if math.IsInf(multiplier, 0) { + return nil, fmt.Errorf("trunc precision %d too large", precision) + } if num >= 0 { return math.Floor(num*multiplier) / multiplier, nil } else { diff --git a/functions/functions_conversion_test.go b/functions/functions_conversion_test.go index eaccfa7..f72f97f 100644 --- a/functions/functions_conversion_test.go +++ b/functions/functions_conversion_test.go @@ -182,6 +182,24 @@ func TestNewConversionFunctions(t *testing.T) { args: []interface{}{3.14159, -1}, wantErr: true, }, + { + name: "trunc nil input returns error", + funcName: "trunc", + args: []interface{}{nil, 2}, + wantErr: true, + }, + { + name: "trunc non-numeric input returns error", + funcName: "trunc", + args: []interface{}{"abc", 2}, + wantErr: true, + }, + { + name: "trunc precision too large returns error", + funcName: "trunc", + args: []interface{}{3.14, 400}, + wantErr: true, + }, } for _, tt := range tests { diff --git a/functions/functions_math.go b/functions/functions_math.go index 079ba23..ef6c351 100644 --- a/functions/functions_math.go +++ b/functions/functions_math.go @@ -353,7 +353,11 @@ func (f *ExpFunction) Execute(ctx *FunctionContext, args []interface{}) (interfa if err != nil { return nil, err } - return math.Exp(val), nil + result := math.Exp(val) + if math.IsNaN(result) || math.IsInf(result, 0) { + return nil, fmt.Errorf("exp(%v) out of range", val) + } + return result, nil } // FloorFunction 向下取整函数 @@ -723,5 +727,9 @@ func (f *PowerFunction) Execute(ctx *FunctionContext, args []interface{}) (inter if err != nil { return nil, err } - return math.Pow(x, y), nil + result := math.Pow(x, y) + if math.IsNaN(result) || math.IsInf(result, 0) { + return nil, fmt.Errorf("pow(%v, %v) out of range", x, y) + } + return result, nil } diff --git a/functions/functions_math_test.go b/functions/functions_math_test.go index b80eec4..504d4a0 100644 --- a/functions/functions_math_test.go +++ b/functions/functions_math_test.go @@ -175,6 +175,27 @@ func TestMathFunctions(t *testing.T) { expected: nil, wantErr: true, }, + { + name: "exp overflow returns error", + funcName: "exp", + args: []interface{}{1000}, + expected: nil, + wantErr: true, + }, + { + name: "pow overflow returns error", + funcName: "pow", + args: []interface{}{10, 400}, + expected: nil, + wantErr: true, + }, + { + name: "pow negative base fractional exp returns error", + funcName: "pow", + args: []interface{}{-2, 0.5}, + expected: nil, + wantErr: true, + }, { name: "log natural", funcName: "log",