LIB: improve safety by ignoring invalid file names for file operations

This commit is contained in:
Julian Ospald 2015-12-27 20:17:14 +01:00
parent 9445574097
commit f2fb4e0be0
No known key found for this signature in database
GPG Key ID: 220CD1C5BDEED020
3 changed files with 28 additions and 1 deletions

View File

@ -324,6 +324,9 @@ pattern InvFN <- (invalidFileName -> (True,_))
-- |Opposite of `InvFN`. -- |Opposite of `InvFN`.
pattern ValFN f <- (invalidFileName -> (False, f)) pattern ValFN f <- (invalidFileName -> (False, f))
pattern AFileInvFN <- (fst . invalidFileName . name . file -> True)
pattern FileInvFN <- (fst . invalidFileName . name -> True)
-- |Matches on directories or symlinks pointing to directories. -- |Matches on directories or symlinks pointing to directories.
-- If the symlink is pointing to a symlink pointing to a directory, then -- If the symlink is pointing to a symlink pointing to a directory, then

View File

@ -71,6 +71,7 @@ data FmIOException = FileDoesNotExist String
| DirDoesExist String | DirDoesExist String
| IsSymlink String | IsSymlink String
| InvalidOperation String | InvalidOperation String
| InvalidFileName
deriving (Show, Typeable) deriving (Show, Typeable)

View File

@ -157,7 +157,8 @@ copyDir :: DirCopyMode
-> AnchoredFile FileInfo -- ^ source dir -> AnchoredFile FileInfo -- ^ source dir
-> AnchoredFile FileInfo -- ^ destination dir -> AnchoredFile FileInfo -- ^ destination dir
-> IO () -> IO ()
copyDir cm (_ :/ SymLink {}) _ = return () copyDir _ AFileInvFN _ = throw InvalidFileName
copyDir _ _ AFileInvFN = throw InvalidFileName
copyDir cm from@(_ :/ Dir fromn _) copyDir cm from@(_ :/ Dir fromn _)
to@(_ :/ Dir {}) to@(_ :/ Dir {})
= do = do
@ -209,6 +210,8 @@ recreateSymlink :: AnchoredFile FileInfo -- ^ the old symlink file
-> AnchoredFile FileInfo -- ^ destination dir of the -> AnchoredFile FileInfo -- ^ destination dir of the
-- new symlink file -- new symlink file
-> IO () -> IO ()
recreateSymlink AFileInvFN _ = throw InvalidFileName
recreateSymlink _ AFileInvFN = throw InvalidFileName
recreateSymlink symf@(_ :/ SymLink {}) recreateSymlink symf@(_ :/ SymLink {})
symdest@(_ :/ Dir {}) symdest@(_ :/ Dir {})
= do = do
@ -221,6 +224,8 @@ recreateSymlink _ _ = throw $ InvalidOperation "wrong input type"
-- |Low-level function to copy a given file to the given path. The fileMode -- |Low-level function to copy a given file to the given path. The fileMode
-- is preserved. -- is preserved.
copyFile' :: FilePath -> FilePath -> IO () copyFile' :: FilePath -> FilePath -> IO ()
copyFile' InvFN _ = throw InvalidFileName
copyFile' _ InvFN = throw InvalidFileName
copyFile' from to = do copyFile' from to = do
fromFstatus <- getSymbolicLinkStatus from fromFstatus <- getSymbolicLinkStatus from
fromContent <- BS.readFile from fromContent <- BS.readFile from
@ -235,6 +240,8 @@ copyFile' from to = do
copyFile :: AnchoredFile FileInfo -- ^ source file copyFile :: AnchoredFile FileInfo -- ^ source file
-> AnchoredFile FileInfo -- ^ destination file -> AnchoredFile FileInfo -- ^ destination file
-> IO () -> IO ()
copyFile AFileInvFN _ = throw InvalidFileName
copyFile _ AFileInvFN = throw InvalidFileName
copyFile (_ :/ SymLink {}) _ = return () copyFile (_ :/ SymLink {}) _ = return ()
copyFile from@(_ :/ RegFile {}) to@(_ :/ RegFile {}) = do copyFile from@(_ :/ RegFile {}) to@(_ :/ RegFile {}) = do
let from' = fullPath from let from' = fullPath from
@ -249,6 +256,8 @@ copyFile _ _ = throw $ InvalidOperation "wrong input type"
copyFileToDir :: AnchoredFile FileInfo copyFileToDir :: AnchoredFile FileInfo
-> AnchoredFile FileInfo -> AnchoredFile FileInfo
-> IO () -> IO ()
copyFileToDir AFileInvFN _ = throw InvalidFileName
copyFileToDir _ AFileInvFN = throw InvalidFileName
copyFileToDir (_ :/ SymLink {}) _ = return () copyFileToDir (_ :/ SymLink {}) _ = return ()
copyFileToDir from@(_ :/ RegFile fn _) copyFileToDir from@(_ :/ RegFile fn _)
to@(_ :/ Dir {}) = to@(_ :/ Dir {}) =
@ -288,6 +297,7 @@ easyCopy _ _ _ = throw $ InvalidOperation "wrong input type"
-- |Deletes a symlink, which can either point to a file or directory. -- |Deletes a symlink, which can either point to a file or directory.
deleteSymlink :: AnchoredFile FileInfo -> IO () deleteSymlink :: AnchoredFile FileInfo -> IO ()
deleteSymlink AFileInvFN = throw InvalidFileName
deleteSymlink f@(_ :/ SymLink {}) deleteSymlink f@(_ :/ SymLink {})
= removeLink (fullPath f) = removeLink (fullPath f)
deleteSymlink _ = throw $ InvalidOperation "wrong input type" deleteSymlink _ = throw $ InvalidOperation "wrong input type"
@ -295,6 +305,7 @@ deleteSymlink _ = throw $ InvalidOperation "wrong input type"
-- |Deletes the given file, never symlinks. -- |Deletes the given file, never symlinks.
deleteFile :: AnchoredFile FileInfo -> IO () deleteFile :: AnchoredFile FileInfo -> IO ()
deleteFile AFileInvFN = throw InvalidFileName
deleteFile (_ :/ SymLink {}) = return () deleteFile (_ :/ SymLink {}) = return ()
deleteFile f@(_ :/ RegFile {}) deleteFile f@(_ :/ RegFile {})
= removeLink (fullPath f) = removeLink (fullPath f)
@ -303,6 +314,7 @@ deleteFile _ = throw $ InvalidOperation "wrong input type"
-- |Deletes the given directory, never symlinks. -- |Deletes the given directory, never symlinks.
deleteDir :: AnchoredFile FileInfo -> IO () deleteDir :: AnchoredFile FileInfo -> IO ()
deleteDir AFileInvFN = throw InvalidFileName
deleteDir (_ :/ SymLink {}) = return () deleteDir (_ :/ SymLink {}) = return ()
deleteDir f@(_ :/ Dir {}) deleteDir f@(_ :/ Dir {})
= removeDirectory (fullPath f) = removeDirectory (fullPath f)
@ -311,6 +323,7 @@ deleteDir _ = throw $ InvalidOperation "wrong input type"
-- |Deletes the given directory recursively. -- |Deletes the given directory recursively.
deleteDirRecursive :: AnchoredFile FileInfo -> IO () deleteDirRecursive :: AnchoredFile FileInfo -> IO ()
deleteDirRecursive AFileInvFN = throw InvalidFileName
deleteDirRecursive f@(_ :/ Dir {}) = do deleteDirRecursive f@(_ :/ Dir {}) = do
let fp = fullPath f let fp = fullPath f
files <- readDirectory' fp files <- readDirectory' fp
@ -346,6 +359,7 @@ easyDelete _ = throw $ InvalidOperation "wrong input type"
-- |Opens a file appropriately by invoking xdg-open. -- |Opens a file appropriately by invoking xdg-open.
openFile :: AnchoredFile a openFile :: AnchoredFile a
-> IO ProcessHandle -> IO ProcessHandle
openFile AFileInvFN = throw InvalidFileName
openFile f = spawnProcess "xdg-open" [fullPath f] openFile f = spawnProcess "xdg-open" [fullPath f]
@ -353,6 +367,7 @@ openFile f = spawnProcess "xdg-open" [fullPath f]
executeFile :: AnchoredFile FileInfo -- ^ program executeFile :: AnchoredFile FileInfo -- ^ program
-> [String] -- ^ arguments -> [String] -- ^ arguments
-> IO ProcessHandle -> IO ProcessHandle
executeFile AFileInvFN _ = throw InvalidFileName
executeFile prog@(_ :/ RegFile {}) args executeFile prog@(_ :/ RegFile {}) args
= spawnProcess (fullPath prog) args = spawnProcess (fullPath prog) args
executeFile _ _ = throw $ InvalidOperation "wrong input type" executeFile _ _ = throw $ InvalidOperation "wrong input type"
@ -366,6 +381,8 @@ executeFile _ _ = throw $ InvalidOperation "wrong input type"
createFile :: AnchoredFile FileInfo -> FileName -> IO () createFile :: AnchoredFile FileInfo -> FileName -> IO ()
createFile AFileInvFN _ = throw InvalidFileName
createFile _ InvFN = throw InvalidFileName
createFile (ADirOrSym td) (ValFN fn) = do createFile (ADirOrSym td) (ValFN fn) = do
let fullp = fullPath td </> fn let fullp = fullPath td </> fn
throwFileDoesExist fullp throwFileDoesExist fullp
@ -375,6 +392,8 @@ createFile _ _ = throw $ InvalidOperation "wrong input type"
createDir :: AnchoredFile FileInfo -> FileName -> IO () createDir :: AnchoredFile FileInfo -> FileName -> IO ()
createDir AFileInvFN _ = throw InvalidFileName
createDir _ InvFN = throw InvalidFileName
createDir (ADirOrSym td) (ValFN fn) = do createDir (ADirOrSym td) (ValFN fn) = do
let fullp = fullPath td </> fn let fullp = fullPath td </> fn
throwDirDoesExist fullp throwDirDoesExist fullp
@ -390,6 +409,8 @@ createDir _ _ = throw $ InvalidOperation "wrong input type"
renameFile :: AnchoredFile FileInfo -> FileName -> IO () renameFile :: AnchoredFile FileInfo -> FileName -> IO ()
renameFile AFileInvFN _ = throw InvalidFileName
renameFile _ InvFN = throw InvalidFileName
renameFile (_ :/ Failed {}) _ = return () renameFile (_ :/ Failed {}) _ = return ()
renameFile af (ValFN fn) = do renameFile af (ValFN fn) = do
let fromf = fullPath af let fromf = fullPath af
@ -404,6 +425,8 @@ renameFile _ _ = throw $ InvalidOperation "wrong input type"
moveFile :: AnchoredFile FileInfo -- ^ file to move moveFile :: AnchoredFile FileInfo -- ^ file to move
-> AnchoredFile FileInfo -- ^ base target directory -> AnchoredFile FileInfo -- ^ base target directory
-> IO () -> IO ()
moveFile AFileInvFN _ = throw InvalidFileName
moveFile _ AFileInvFN = throw InvalidFileName
moveFile from to@(_ :/ Dir {}) = do moveFile from to@(_ :/ Dir {}) = do
let from' = fullPath from let from' = fullPath from
to' = fullPath to </> (name . file $ from) to' = fullPath to </> (name . file $ from)