Skip to content

Commit 423e6af

Browse files
committed
Check that filenames are ASCII instead of silent corruption (see #6)
1 parent 0ed8145 commit 423e6af

File tree

5 files changed

+24
-5
lines changed

5 files changed

+24
-5
lines changed

Codec/Archive/Tar/Index/Internal.hs

+2-1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import qualified Codec.Archive.Tar.Index.StringTable as StringTable
6767
import Codec.Archive.Tar.Index.StringTable (StringTable, StringTableBuilder)
6868
import qualified Codec.Archive.Tar.Index.IntTrie as IntTrie
6969
import Codec.Archive.Tar.Index.IntTrie (IntTrie, IntTrieBuilder)
70+
import Codec.Archive.Tar.PackAscii
7071

7172
import qualified System.FilePath.Posix as FilePath
7273
import Data.Monoid (Monoid(..))
@@ -174,7 +175,7 @@ toComponentIds table =
174175
lookupComponents []
175176
. filter (/= BS.Char8.singleton '.')
176177
. splitDirectories
177-
. BS.Char8.pack
178+
. packAscii
178179
where
179180
lookupComponents cs' [] = Just (reverse cs')
180181
lookupComponents cs' (c:cs) = case StringTable.lookup table c of

Codec/Archive/Tar/PackAscii.hs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module Codec.Archive.Tar.PackAscii
2+
( packAscii
3+
) where
4+
5+
import qualified Data.ByteString.Char8 as BS.Char8
6+
import Data.Char
7+
import GHC.Stack
8+
9+
-- | We should really migrate to 'OsPath' from 'filepath',
10+
-- but for now let's not corrupt data silently.
11+
packAscii :: HasCallStack => FilePath -> BS.Char8.ByteString
12+
packAscii xs
13+
| all isAscii xs = BS.Char8.pack xs
14+
| otherwise = error $ "packAscii: only ASCII filenames are supported, but got " ++ xs

Codec/Archive/Tar/Types.hs

+6-4
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ import qualified System.FilePath.Windows as FilePath.Windows
7474
import System.Posix.Types
7575
( FileMode )
7676

77+
import Codec.Archive.Tar.PackAscii
78+
7779
type FileSize = Int64
7880
-- | The number of seconds since the UNIX epoch
7981
type EpochTime = Int64
@@ -357,14 +359,14 @@ splitLongPath :: FilePath -> Either String TarPath
357359
splitLongPath path =
358360
case packName nameMax (reverse (FilePath.Posix.splitPath path)) of
359361
Left err -> Left err
360-
Right (name, []) -> Right $! TarPath (BS.Char8.pack name)
362+
Right (name, []) -> Right $! TarPath (packAscii name)
361363
BS.empty
362364
Right (name, first:rest) -> case packName prefixMax remainder of
363365
Left err -> Left err
364366
Right (_ , (_:_)) -> Left $ "Filename " ++ path ++
365367
" too long (cannot split)"
366-
Right (prefix, []) -> Right $! TarPath (BS.Char8.pack name)
367-
(BS.Char8.pack prefix)
368+
Right (prefix, []) -> Right $! TarPath (packAscii name)
369+
(packAscii prefix)
368370
where
369371
-- drop the '/' between the name and prefix:
370372
remainder = init first : rest
@@ -399,7 +401,7 @@ instance NFData LinkTarget where
399401
-- characters.
400402
--
401403
toLinkTarget :: FilePath -> Maybe LinkTarget
402-
toLinkTarget path | length path <= 100 = Just $! LinkTarget (BS.Char8.pack path)
404+
toLinkTarget path | length path <= 100 = Just $! LinkTarget (packAscii path)
403405
| otherwise = Nothing
404406

405407
-- | Convert a tar 'LinkTarget' to a native 'FilePath'.

changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ See also http://pvp.haskell.org/faq
77
* Speed up `fromTarPathToPosixPath`
88
* Set permissions on extracted files
99
* Handle > 8 GB files
10+
* Prohibit non-ASCII file names instead of silent corruption
1011

1112
0.5.1.1 Herbert Valerio Riedel <[email protected]> August 2019
1213

tar.cabal

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ library tar-internal
6262
Codec.Archive.Tar.Read
6363
Codec.Archive.Tar.Write
6464
Codec.Archive.Tar.Pack
65+
Codec.Archive.Tar.PackAscii
6566
Codec.Archive.Tar.Unpack
6667
Codec.Archive.Tar.Index.StringTable
6768
Codec.Archive.Tar.Index.IntTrie

0 commit comments

Comments
 (0)