diff --git a/src/internal/file_operations.go b/src/internal/file_operations.go index 8632512a..3019d443 100644 --- a/src/internal/file_operations.go +++ b/src/internal/file_operations.go @@ -46,6 +46,30 @@ func getDriveLetter(path string) string { return strings.ToUpper(string(path[0])) } +// isSubDir check if a path is inside another path to prevent unwanted recursive operations +func isSubDir(src string, dst string) (bool, error) { + absSrc, err := filepath.Abs(src) + if err != nil { + return false, err + } + + absDst, err := filepath.Abs(filepath.Dir(dst)) + if err != nil { + return false, err + } + + rel, err := filepath.Rel(absSrc, absDst) + if err != nil { + return false, err + } + if rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) { + return false, nil + } + + return true, nil + +} + // moveElement moves a file or directory efficiently func moveElement(src, dst string) error { // Check if source and destination are on the same partition diff --git a/src/internal/handle_file_operations.go b/src/internal/handle_file_operations.go index 98f47800..f8fcd22d 100644 --- a/src/internal/handle_file_operations.go +++ b/src/internal/handle_file_operations.go @@ -1,6 +1,7 @@ package internal import ( + "fmt" "log/slog" "os" "os/exec" @@ -470,10 +471,18 @@ func (m *model) pasteItem() { } errMessage := "cut item error" - if m.copyItems.cut && !isExternalDiskPath(filePath) { - err = moveElement(filePath, filepath.Join(panel.location, filepath.Base(filePath))) + + dstPath := filepath.Join(panel.location, filepath.Base(filePath)) + subDir, err := isSubDir(filePath, dstPath) + + if err != nil { + // cannot compare source and destination paths, so just fail with the given error + } else if subDir { + err = fmt.Errorf("failed to paste: cannot paste item, '%s', into itself, %s", filePath, dstPath) + } else if m.copyItems.cut && !isExternalDiskPath(filePath) { + err = moveElement(filePath, dstPath) } else { - err = pasteDir(filePath, filepath.Join(panel.location, filepath.Base(filePath)), id, m) + err = pasteDir(filePath, dstPath, id, m) if err != nil { errMessage = "paste item error" } else {