Add some limits

This commit is contained in:
binwiederhier
2025-07-19 16:46:53 +02:00
parent 57df16dd62
commit dde07adbdc
9 changed files with 77 additions and 13 deletions

View File

@@ -132,7 +132,7 @@ func toRawJSON(v any) string {
if err != nil {
panic(err)
}
return string(output)
return output
}
// mustToRawJSON encodes an item into a JSON string with no escaping of HTML characters.

View File

@@ -14,6 +14,11 @@ import (
"time"
)
const (
loopExecutionLimit = 10_000 // Limit the number of loop executions to prevent execution from taking too long
stringLengthLimit = 100_000 // Limit the length of strings to prevent memory issues
)
// TxtFuncMap produces the function map.
//
// Use this to pass the functions into the template engine:
@@ -58,7 +63,7 @@ var genericMap = map[string]any{
},
"substr": substring,
// Switch order so that "foo" | repeat 5
"repeat": func(count int, str string) string { return strings.Repeat(str, count) },
"repeat": repeat,
"trimAll": func(a, b string) string { return strings.Trim(b, a) },
"trimSuffix": func(a, b string) string { return strings.TrimSuffix(b, a) },
"trimPrefix": func(a, b string) string { return strings.TrimPrefix(b, a) },

View File

@@ -127,7 +127,15 @@ func until(count int) []int {
}
func untilStep(start, stop, step int) []int {
v := []int{}
var v []int
if step == 0 {
return v
}
iterations := math.Abs(float64(stop)-float64(start)) / float64(step)
if iterations > loopExecutionLimit {
panic(fmt.Sprintf("too many iterations in untilStep; max allowed is %d, got %f", loopExecutionLimit, iterations))
}
if stop < start {
if step >= 0 {

View File

@@ -187,3 +187,12 @@ func substring(start, end int, s string) string {
}
return s[start:end]
}
func repeat(count int, str string) string {
if count > loopExecutionLimit {
panic(fmt.Sprintf("repeat count %d exceeds limit of %d", count, loopExecutionLimit))
} else if count*len(str) >= stringLengthLimit {
panic(fmt.Sprintf("repeat count %d with string length %d exceeds limit of %d", count, len(str), stringLengthLimit))
}
return strings.Repeat(str, count)
}

View File

@@ -7,7 +7,7 @@ import (
)
// ErrWriteTimeout is returned when a write timed out
var ErrWriteTimeout = errors.New("write operation failed due to timeout since creation")
var ErrWriteTimeout = errors.New("write operation failed due to timeout")
// TimeoutWriter wraps an io.Writer that will time out after the given timeout
type TimeoutWriter struct {
@@ -28,7 +28,7 @@ func NewTimeoutWriter(w io.Writer, timeout time.Duration) *TimeoutWriter {
// Write implements the io.Writer interface, failing if called after the timeout period from creation.
func (tw *TimeoutWriter) Write(p []byte) (n int, err error) {
if time.Since(tw.start) > tw.timeout {
return 0, errors.New("write operation failed due to timeout since creation")
return 0, ErrWriteTimeout
}
return tw.writer.Write(p)
}