File CVE-2025-68156-limit-recursion-depth.patch of Package coredns-for-k8s1.33
From 2a07330648d2f827f92a95b4c9976d0c4f971ee6 Mon Sep 17 00:00:00 2001
From: Ville Vesilehto <ville@vesilehto.fi>
Date: Wed, 3 Dec 2025 14:29:38 +0200
Subject: [PATCH] fix(builtin): limit recursion depth
Add builtin.MaxDepth (default 10k) to prevent stack overflows when
processing deeply nested or cyclic structures in builtin functions.
The functions flatten, min, max, mean, and median now return a
"recursion depth exceeded" error instead of crashing the runtime.
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
---
builtin/builtin.go | 18 +++++---
builtin/builtin_test.go | 97 +++++++++++++++++++++++++++++++++++++++++
builtin/lib.go | 33 ++++++++++----
3 files changed, 134 insertions(+), 14 deletions(-)
Index: coredns-1.12.0/vendor/github.com/expr-lang/expr/builtin/lib.go
===================================================================
--- coredns-1.12.0.orig/vendor/github.com/expr-lang/expr/builtin/lib.go
+++ coredns-1.12.0/vendor/github.com/expr-lang/expr/builtin/lib.go
@@ -258,7 +258,10 @@ func String(arg any) any {
return fmt.Sprintf("%v", arg)
}
-func minMax(name string, fn func(any, any) bool, args ...any) (any, error) {
+func minMax(name string, fn func(any, any) bool, depth int, args ...any) (any, error) {
+ if depth > MaxDepth {
+ return nil, ErrorMaxDepth
+ }
var val any
for _, arg := range args {
rv := reflect.ValueOf(deref.Deref(arg))
@@ -266,7 +269,7 @@ func minMax(name string, fn func(any, an
case reflect.Array, reflect.Slice:
size := rv.Len()
for i := 0; i < size; i++ {
- elemVal, err := minMax(name, fn, rv.Index(i).Interface())
+ elemVal, err := minMax(name, fn, depth+1, rv.Index(i).Interface())
if err != nil {
return nil, err
}
@@ -299,7 +302,10 @@ func minMax(name string, fn func(any, an
return val, nil
}
-func mean(args ...any) (int, float64, error) {
+func mean(depth int, args ...any) (int, float64, error) {
+ if depth > MaxDepth {
+ return 0, 0, ErrorMaxDepth
+ }
var total float64
var count int
@@ -309,7 +315,7 @@ func mean(args ...any) (int, float64, er
case reflect.Array, reflect.Slice:
size := rv.Len()
for i := 0; i < size; i++ {
- elemCount, elemSum, err := mean(rv.Index(i).Interface())
+ elemCount, elemSum, err := mean(depth+1, rv.Index(i).Interface())
if err != nil {
return 0, 0, err
}
@@ -332,7 +338,10 @@ func mean(args ...any) (int, float64, er
return count, total, nil
}
-func median(args ...any) ([]float64, error) {
+func median(depth int, args ...any) ([]float64, error) {
+ if depth > MaxDepth {
+ return nil, ErrorMaxDepth
+ }
var values []float64
for _, arg := range args {
@@ -341,7 +350,7 @@ func median(args ...any) ([]float64, err
case reflect.Array, reflect.Slice:
size := rv.Len()
for i := 0; i < size; i++ {
- elems, err := median(rv.Index(i).Interface())
+ elems, err := median(depth+1, rv.Index(i).Interface())
if err != nil {
return nil, err
}
Index: coredns-1.12.0/vendor/github.com/expr-lang/expr/builtin/builtin.go
===================================================================
--- coredns-1.12.0.orig/vendor/github.com/expr-lang/expr/builtin/builtin.go
+++ coredns-1.12.0/vendor/github.com/expr-lang/expr/builtin/builtin.go
@@ -3,6 +3,7 @@ package builtin
import (
"encoding/base64"
"encoding/json"
+ "errors"
"fmt"
"reflect"
"sort"
@@ -16,6 +17,10 @@ import (
var (
Index map[string]int
Names []string
+
+ // MaxDepth limits the recursion depth for nested structures.
+ MaxDepth = 10000
+ ErrorMaxDepth = errors.New("recursion depth exceeded")
)
func init() {
@@ -377,7 +382,7 @@ var Builtins = []*Function{
{
Name: "max",
Func: func(args ...any) (any, error) {
- return minMax("max", runtime.Less, args...)
+ return minMax("max", runtime.Less, 0, args...)
},
Validate: func(args []reflect.Type) (reflect.Type, error) {
return validateAggregateFunc("max", args)
@@ -386,7 +391,7 @@ var Builtins = []*Function{
{
Name: "min",
Func: func(args ...any) (any, error) {
- return minMax("min", runtime.More, args...)
+ return minMax("min", runtime.More, 0, args...)
},
Validate: func(args []reflect.Type) (reflect.Type, error) {
return validateAggregateFunc("min", args)
@@ -395,7 +400,7 @@ var Builtins = []*Function{
{
Name: "mean",
Func: func(args ...any) (any, error) {
- count, sum, err := mean(args...)
+ count, sum, err := mean(0, args...)
if err != nil {
return nil, err
}
@@ -411,7 +416,7 @@ var Builtins = []*Function{
{
Name: "median",
Func: func(args ...any) (any, error) {
- values, err := median(args...)
+ values, err := median(0, args...)
if err != nil {
return nil, err
}