fix: drop action outputs whose value exceeds the size limit (#1070)

`SetOutputs` logged "ignore output because the value is too long" for values
larger than 1 MiB but then fell through and stored the value anyway, sending
it upstream via `UpdateTask`. The key-too-long branch directly above correctly
skips oversized keys with `continue`; this adds the same `continue` to the
value branch so the size guard is actually enforced and the log message
matches the behavior.

Adds regression coverage in `TestReporter_SetOutputs` for an oversized value
(dropped) and a value at exactly the 1 MiB limit (retained).

---------

Co-authored-by: Zettat123 <39446+zettat123@noreply.gitea.com>
Co-authored-by: Zettat123 <zettat123@gmail.com>
Reviewed-on: https://gitea.com/gitea/runner/pulls/1070
Reviewed-by: Zettat123 <39446+zettat123@noreply.gitea.com>
This commit is contained in:
Nicolas
2026-07-14 14:28:57 +00:00
parent 554b3b7671
commit d53538ac38
2 changed files with 28 additions and 7 deletions

View File

@@ -26,6 +26,12 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
)
// Size limits for the outputs reported to the server.
const (
maxOutputKeyLen = 255
maxOutputValueLen = 1024 * 1024 // 1 MiB
)
type Reporter struct {
ctx context.Context
cancel context.CancelFunc
@@ -390,13 +396,15 @@ func (r *Reporter) SetOutputs(outputs map[string]string) {
defer r.stateMu.Unlock()
for k, v := range outputs {
if len(k) > 255 {
r.logf("ignore output because the key is too long: %q", k)
if l := len(k); l > maxOutputKeyLen {
log.Warnf("ignore output %q because the key is too long: %d > %d", k, l, maxOutputKeyLen)
r.logf("ignore output %q because the key is too long: %d > %d", k, l, maxOutputKeyLen)
continue
}
if l := len(v); l > 1024*1024 {
log.Println("ignore output because the value is too long:", k, l)
r.logf("ignore output because the value %q is too long: %d", k, l)
if l := len(v); l > maxOutputValueLen {
log.Warnf("ignore output %q because the value is too long: %d > %d", k, l, maxOutputValueLen)
r.logf("ignore output %q because the value is too long: %d > %d", k, l, maxOutputValueLen)
continue
}
if _, ok := r.outputs.Load(k); ok {
continue

View File

@@ -1020,11 +1020,24 @@ func TestReporter_SetOutputs(t *testing.T) {
got, _ = r.outputs.Load("foo")
assert.Equal(t, "bar", got)
// keys longer than 255 chars are dropped
longKey := strings.Repeat("k", 256)
// keys longer than maxOutputKeyLen are dropped
longKey := strings.Repeat("k", maxOutputKeyLen+1)
r.SetOutputs(map[string]string{longKey: "v"})
_, ok = r.outputs.Load(longKey)
assert.False(t, ok)
// values longer than maxOutputValueLen are dropped
longValue := strings.Repeat("v", maxOutputValueLen+1)
r.SetOutputs(map[string]string{"big": longValue})
_, ok = r.outputs.Load("big")
assert.False(t, ok)
// a value at exactly the limit is still stored
maxValue := strings.Repeat("v", maxOutputValueLen)
r.SetOutputs(map[string]string{"atlimit": maxValue})
got, ok = r.outputs.Load("atlimit")
require.True(t, ok)
assert.Len(t, got, maxOutputValueLen)
}
func TestReporter_EffectiveCloseTimeout(t *testing.T) {