39 lines
1.1 KiB
Go
39 lines
1.1 KiB
Go
package builtin
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// resolvePath erzwingt die Pfad-Regel aus Abschnitt 5.3: nur unterhalb von
|
|
// RepoRoot, Symlinks werden aufgelöst und erneut geprüft.
|
|
func resolvePath(repoRoot, cwd, path string) (string, error) {
|
|
if !filepath.IsAbs(path) {
|
|
path = filepath.Join(cwd, path)
|
|
}
|
|
clean := filepath.Clean(path)
|
|
|
|
root, err := filepath.EvalSymlinks(repoRoot)
|
|
if err != nil {
|
|
return "", fmt.Errorf("repo root nicht auflösbar: %w", err)
|
|
}
|
|
|
|
// Symlinks im Zielpfad auflösen, soweit er existiert; fehlt er (z.B. bei
|
|
// write), am nächsten existierenden Vorfahren prüfen.
|
|
resolved := clean
|
|
if real, err := filepath.EvalSymlinks(clean); err == nil {
|
|
resolved = real
|
|
} else {
|
|
dir := filepath.Dir(clean)
|
|
if real, err := filepath.EvalSymlinks(dir); err == nil {
|
|
resolved = filepath.Join(real, filepath.Base(clean))
|
|
}
|
|
}
|
|
|
|
rel, err := filepath.Rel(root, resolved)
|
|
if err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
|
|
return "", fmt.Errorf("path escapes repo root: %s", path)
|
|
}
|
|
return clean, nil
|
|
}
|