From 33a97bfcd323e22dc60ff4402adcfe9047b3bd7b Mon Sep 17 00:00:00 2001 From: Shaurya Kesarwani Date: Mon, 26 Oct 2026 12:14:41 +0530 Subject: [PATCH] Return an error instead of panicking on integer division by zero Value.Divide and Value.Modulo used Go's integer / and % directly when both operands were ints, so a selector such as `1 / 0` or `5 % 0` crashed the process with "panic: runtime error: integer divide by zero". Check the divisor first and return ErrDivisionByZero instead. --- model/error.go | 8 +++++++- model/value_math.go | 6 ++++++ model/value_math_test.go | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/model/error.go b/model/error.go index 8cadf36a..f7b75b92 100644 --- a/model/error.go +++ b/model/error.go @@ -1,6 +1,12 @@ package model -import "fmt" +import ( + "errors" + "fmt" +) + +// ErrDivisionByZero is returned when an integer is divided by zero. +var ErrDivisionByZero = errors.New("integer division by zero") // MapKeyNotFound is returned when a key is not found in a map. type MapKeyNotFound struct { diff --git a/model/value_math.go b/model/value_math.go index e7b7a6cf..24e9a225 100644 --- a/model/value_math.go +++ b/model/value_math.go @@ -174,6 +174,9 @@ func (v *Value) Divide(other *Value) (*Value, error) { if err != nil { return nil, err } + if b == 0 { + return nil, ErrDivisionByZero + } return NewValue(a / b), nil } if v.IsFloat() && other.IsFloat() { @@ -223,6 +226,9 @@ func (v *Value) Modulo(other *Value) (*Value, error) { if err != nil { return nil, err } + if b == 0 { + return nil, ErrDivisionByZero + } return NewValue(a % b), nil } if v.IsFloat() && other.IsFloat() { diff --git a/model/value_math_test.go b/model/value_math_test.go index f6b80e54..a10fa115 100644 --- a/model/value_math_test.go +++ b/model/value_math_test.go @@ -1,6 +1,7 @@ package model_test import ( + "errors" "testing" "github.com/tomwright/dasel/v3/model" @@ -148,3 +149,18 @@ func TestValue_Modulo(t *testing.T) { t.Run("float", run(model.NewFloatValue(10), model.NewFloatValue(3), model.NewFloatValue(1))) }) } + +func TestValue_IntegerDivisionByZero(t *testing.T) { + t.Run("divide", func(t *testing.T) { + _, err := model.NewIntValue(1).Divide(model.NewIntValue(0)) + if !errors.Is(err, model.ErrDivisionByZero) { + t.Errorf("expected %v, got %v", model.ErrDivisionByZero, err) + } + }) + t.Run("modulo", func(t *testing.T) { + _, err := model.NewIntValue(1).Modulo(model.NewIntValue(0)) + if !errors.Is(err, model.ErrDivisionByZero) { + t.Errorf("expected %v, got %v", model.ErrDivisionByZero, err) + } + }) +}