github.com/anacrolix/torrent@v1.61.0/storage/safe-path.go (about)

     1  package storage
     2  
     3  import (
     4  	"errors"
     5  	"path/filepath"
     6  	"strings"
     7  )
     8  
     9  // Get the first file path component. We can't use filepath.Split because that breaks off the last
    10  // one. We could optimize this to avoid allocating a slice down the track.
    11  func firstComponent(filePath string) string {
    12  	return strings.SplitN(filePath, string(filepath.Separator), 2)[0]
    13  }
    14  
    15  // Combines file info path components, ensuring the result won't escape into parent directories.
    16  func ToSafeFilePath(fileInfoComponents ...string) (string, error) {
    17  	safeComps := make([]string, 0, len(fileInfoComponents))
    18  	for _, comp := range fileInfoComponents {
    19  		safeComps = append(safeComps, filepath.Clean(comp))
    20  	}
    21  	safeFilePath := filepath.Join(safeComps...)
    22  	fc := firstComponent(safeFilePath)
    23  	switch fc {
    24  	case "..":
    25  		return "", errors.New("escapes root dir")
    26  	default:
    27  		return safeFilePath, nil
    28  	}
    29  }