fix: limit run command output to 2MB

This commit is contained in:
Gareth George
2025-04-30 01:20:21 -07:00
parent 3ab62710a1
commit 01d9c9f383
3 changed files with 33 additions and 3 deletions

View File

@@ -2,6 +2,7 @@ package ioutil
import (
"bytes"
"fmt"
"io"
"sync"
"sync/atomic"
@@ -101,3 +102,25 @@ func (w *SizeTrackingWriter) Write(p []byte) (n int, err error) {
func (w *SizeTrackingWriter) Size() uint64 {
return w.size.Load()
}
type SizeLimitedWriter struct {
SizeTrackingWriter
Limit uint64
}
var _ io.Writer = &SizeLimitedWriter{}
func (w *SizeLimitedWriter) Write(p []byte) (n int, err error) {
size := w.Size()
if size+uint64(len(p)) > w.Limit {
p = p[:w.Limit-size]
err = fmt.Errorf("size limit exceeded: %d bytes written, limit is %d bytes", size, w.Limit)
}
var e error
n, e = w.Writer.Write(p)
if e != nil {
err = e
}
return
}

View File

@@ -9,6 +9,8 @@ import (
"github.com/garethgeorge/backrest/internal/ioutil"
)
var DefaultCommandOutputSizeLimit uint64 = 2_000_000 // 2MB
func NewOneoffRunCommandTask(repo *v1.Repo, planID string, flowID int64, at time.Time, command string) Task {
return &GenericOneoffTask{
OneoffTask: OneoffTask{
@@ -54,9 +56,13 @@ func runCommandHelper(ctx context.Context, st ScheduledTask, taskRunner TaskRunn
return fmt.Errorf("get logref writer: %w", err)
}
defer writer.Close()
sizeWriter := &ioutil.SizeTrackingWriter{Writer: writer}
sizeWriter := &ioutil.SizeLimitedWriter{
SizeTrackingWriter: ioutil.SizeTrackingWriter{Writer: writer},
Limit: DefaultCommandOutputSizeLimit, // 2 MB max output size
}
defer func() {
runCmdOp.OutputSizeBytes = int64(sizeWriter.Size())
size := sizeWriter.Size()
runCmdOp.OutputSizeBytes = int64(size)
}()
runCmdOp.OutputLogref = id

View File

@@ -145,7 +145,7 @@ func removeOldVersions(installDir string) {
func installResticHelper(resticInstallPath string) {
if _, err := os.Stat(resticInstallPath); err == nil {
zap.S().Infof("replacing restic binary in data dir due to failed check: %w", err)
zap.S().Infof("replacing restic binary in data dir due to failed check: %v", err)
if err := os.Remove(resticInstallPath); err != nil {
zap.S().Errorf("failed to remove old restic binary %v: %v", resticInstallPath, err)
}
@@ -211,6 +211,7 @@ func tryFindOrInstall() (string, error) {
// Check again after acquiring the lock.
if err := assertResticVersion(resticInstallPath); err != nil {
zap.S().Errorf("could not verify version of binary %v: %v", resticInstallPath, err)
installResticHelper(resticInstallPath)
}
}