diff --git a/test/Tests/MediaBag.hs b/test/Tests/MediaBag.hs index fbc9eb153..8c7be1fe3 100644 --- a/test/Tests/MediaBag.hs +++ b/test/Tests/MediaBag.hs @@ -7,42 +7,50 @@ import Test.Tasty.HUnit import Text.Pandoc.Class.IO (extractMedia) import Text.Pandoc.Class (fillMediaBag, runIOorExplode) import System.IO.Temp (withTempDirectory) -import Text.Pandoc.Shared (inDirectory) import System.FilePath import Text.Pandoc.Builder as B -import System.Directory (doesFileExist, copyFile) +import qualified Data.Text as T +import System.Directory (doesFileExist, makeAbsolute) tests :: [TestTree] tests = [ testCase "test fillMediaBag & extractMedia" $ - withTempDirectory "." "extractMediaTest" $ \tmpdir -> inDirectory tmpdir $ do - copyFile "../../test/lalune.jpg" "moon.jpg" + withTempDirectory "." "extractMediaTest" $ \tmpdir -> do + -- Use absolute paths so the test does not need to change + -- the process-wide current directory (which is not thread-safe + -- and breaks other tests running in parallel). + absTmpdir <- makeAbsolute tmpdir + absLalune <- makeAbsolute "lalune.jpg" let d = B.doc $ - B.para (B.image "../../test/lalune.jpg" "" mempty) <> - B.para (B.image "moon.jpg" "" mempty) <> + -- simple relative path -> extracted with original name + B.para (B.image "lalune.jpg" "" mempty) <> + -- absolute path -> extracted with hashed name + B.para (B.image (T.pack absLalune) "" mempty) <> B.para (B.image "data:image/png;base64,cHJpbnQgImhlbGxvIgo=;.lua+%2f%2e%2e%2f%2e%2e%2fa%2elua" "" mempty) <> B.para (B.image "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" "" mempty) + let fooDir = absTmpdir "foo" runIOorExplode $ do fillMediaBag d - extractMedia "foo" d - exists1 <- doesFileExist ("foo" "moon.jpg") + extractMedia fooDir d + exists1 <- doesFileExist (fooDir "lalune.jpg") assertBool "file in directory is not extracted with original name" exists1 - exists2 <- doesFileExist ("foo" "f9d88c3dbe18f6a7f5670e994a947d51216cdf0e.jpg") - assertBool "file above directory is not extracted with hashed name" exists2 - exists3 <- doesFileExist ("foo" "2a0eaa89f43fada3e6c577beea4f2f8f53ab6a1d.png") - exists4 <- doesFileExist "a.lua" + exists2 <- doesFileExist (fooDir "f9d88c3dbe18f6a7f5670e994a947d51216cdf0e.jpg") + assertBool "file with absolute path is not extracted with hashed name" exists2 + exists3 <- doesFileExist (fooDir "2a0eaa89f43fada3e6c577beea4f2f8f53ab6a1d.png") + exists4 <- doesFileExist (absTmpdir "a.lua") assertBool "data uri with malicious payload gets written outside of destination dir" (exists3 && not exists4) - exists5 <- doesFileExist ("foo" "d5fceb6532643d0d84ffe09c40c481ecdf59e15a.gif") + exists5 <- doesFileExist (fooDir "d5fceb6532643d0d84ffe09c40c481ecdf59e15a.gif") assertBool "data uri with gif is not properly decoded" exists5 -- double-encoded version: let e = B.doc $ B.para (B.image "data:image/png;base64,cHJpbnQgInB3bmVkIgo=;.lua+%252f%252e%252e%252f%252e%252e%252fb%252elua" "" mempty) + let barDir = absTmpdir "bar" runIOorExplode $ do fillMediaBag e - extractMedia "bar" e - exists6 <- doesFileExist ("bar" "772ceca21a2751863ec46cb23db0e7fc35b9cff8.png") - exists7 <- doesFileExist "b.lua" + extractMedia barDir e + exists6 <- doesFileExist (barDir "772ceca21a2751863ec46cb23db0e7fc35b9cff8.png") + exists7 <- doesFileExist (absTmpdir "b.lua") assertBool "data uri with double-encoded malicious payload gets written outside of destination dir" (exists6 && not exists7) ]