Files
aego/asset/pipeline/external_read.go
sanspie a46347e2c6
ci-platforms / darwin arm64 smoke (push) Skipped
ci / build (amd64, linux, ubuntu-24.04) (push) Failing after 12m19s
ci-platforms / darwin amd64 smoke (push) Skipped
ci-platforms / windows amd64 smoke (push) Skipped
github-native / gitea-pending (push) Skipped
github-native / darwin amd64 native (push) Skipped
github-native / linux amd64 native (push) Skipped
github-native / windows amd64 native (push) Skipped
github-native / darwin arm64 native (push) Skipped
github-native / gitea-result (push) Skipped
ci / checks (push) Failing after 23m57s
ci / release (push) Skipped
GitHub / windows amd64 native GitHub-hosted native CI: failure
GitHub / darwin arm64 native GitHub-hosted native CI: failure
GitHub / darwin amd64 native GitHub-hosted native CI: failure
GitHub / linux amd64 native GitHub-hosted native CI: success
editor: add art studio and stage 12.5 workflows
2026-11-08 18:47:57 +03:00

55 lines
1.4 KiB
Go

package pipeline
import (
"errors"
"io"
"math"
"os"
)
// ErrExternalFileLimit indicates a special file or an input over budget.
var ErrExternalFileLimit = errors.New("external file is not regular or exceeds the size limit")
// ReadExternalFile reads a user-selected input with a strict byte budget.
// Check before opening as well as after opening so a named pipe is not normally
// opened as though it were an ordinary document. Symlinks are followed because
// the caller explicitly selected the source; project writes use separate guards.
func ReadExternalFile(name string, limit int64) ([]byte, error) {
if limit <= 0 || limit == math.MaxInt64 {
return nil, errors.New("invalid external file size limit")
}
check := func(info os.FileInfo) error {
if !info.Mode().IsRegular() || info.Size() < 0 || info.Size() > limit {
return ErrExternalFileLimit
}
return nil
}
info, err := os.Stat(name)
if err != nil {
return nil, err
}
if err := check(info); err != nil {
return nil, err
}
f, err := os.Open(name)
if err != nil {
return nil, err
}
defer f.Close()
info, err = f.Stat()
if err != nil {
return nil, err
}
if err := check(info); err != nil {
return nil, err
}
data, err := io.ReadAll(io.LimitReader(f, limit+1))
if err != nil {
return nil, err
}
if int64(len(data)) > limit {
return nil, ErrExternalFileLimit
}
return data, nil
}