aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/aflow/loop.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2026-01-27 10:18:40 +0100
committerDmitry Vyukov <dvyukov@google.com>2026-01-27 09:30:55 +0000
commit9a514c2f136aa42ebe9212c4ab1a526cfbe933c3 (patch)
treee795a6fb0e5248724e68cc259e7374443238e437 /pkg/aflow/loop.go
parent43e1df1d9b982f24e3ccba50cf8881eed86d8994 (diff)
pkg/aflow: add explicit DoWhile.MaxIterations
Add DoWhile.MaxIterations and make it mandatory. I think it's useful to make workflow implementer to think explicitly about a reasonable cap on the number of iterations.
Diffstat (limited to 'pkg/aflow/loop.go')
-rw-r--r--pkg/aflow/loop.go12
1 files changed, 9 insertions, 3 deletions
diff --git a/pkg/aflow/loop.go b/pkg/aflow/loop.go
index e074d4217..18a7cafa8 100644
--- a/pkg/aflow/loop.go
+++ b/pkg/aflow/loop.go
@@ -18,6 +18,9 @@ type DoWhile struct {
// Exit condition. It should be a string state variable.
// The loop exists when the variable is empty.
While string
+ // Max interations for the loop.
+ // Must be specified to avoid unintended effectively infinite loops.
+ MaxIterations int
loopVars map[string]reflect.Type
}
@@ -43,8 +46,7 @@ func (dw *DoWhile) loop(ctx *Context) error {
}
ctx.state[name] = reflect.Zero(typ).Interface()
}
- const maxIters = 100
- for iter := 0; iter < maxIters; iter++ {
+ for iter := 0; iter < dw.MaxIterations; iter++ {
span := &trajectory.Span{
Type: trajectory.SpanLoopIteration,
Name: fmt.Sprint(iter),
@@ -60,10 +62,14 @@ func (dw *DoWhile) loop(ctx *Context) error {
return nil
}
}
- return fmt.Errorf("DoWhile loop is going in cycles for %v iterations", maxIters)
+ return fmt.Errorf("DoWhile loop is going in cycles for %v iterations", dw.MaxIterations)
}
func (dw *DoWhile) verify(ctx *verifyContext) {
+ if max := 1000; dw.MaxIterations <= 0 || dw.MaxIterations >= max {
+ ctx.errorf("DoWhile", "bad MaxIterations value %v, should be within [1, %v]",
+ dw.MaxIterations, max)
+ }
// Verification of loops is a bit tricky.
// Normally we require each variable to be defined before use, but loops violate
// the assumption. An action in a loop body may want to use a variable produced