diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2026-01-27 10:18:40 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2026-01-27 09:30:55 +0000 |
| commit | 9a514c2f136aa42ebe9212c4ab1a526cfbe933c3 (patch) | |
| tree | e795a6fb0e5248724e68cc259e7374443238e437 /pkg/aflow/loop.go | |
| parent | 43e1df1d9b982f24e3ccba50cf8881eed86d8994 (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.go | 12 |
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 |
