From 97f99171b8b6a2f47b465cc7aa763c5037b8ee9c Mon Sep 17 00:00:00 2001 From: Javier Sagredo Date: Sat, 18 Nov 2023 20:39:35 +0100 Subject: [PATCH] Use Base16 hash for script path. Issue #9334 shows that `%` characters on Windows result in invalid paths, also `/` characters on Linux create invalid paths. This changes from using base64 to using base16 with the same length we use for unit-ids. --- cabal-install/cabal-install.cabal | 1 - cabal-install/src/Distribution/Client/HashValue.hs | 5 ----- cabal-install/src/Distribution/Client/ScriptUtils.hs | 14 ++++++-------- cabal-testsuite/cabal-testsuite.cabal | 3 ++- cabal-testsuite/src/Test/Cabal/Prelude.hs | 5 ++--- changelog.d/base16-script-cache | 9 +++++++++ 6 files changed, 19 insertions(+), 18 deletions(-) create mode 100644 changelog.d/base16-script-cache diff --git a/cabal-install/cabal-install.cabal b/cabal-install/cabal-install.cabal index 0a5e55bc3..aee621a99 100644 --- a/cabal-install/cabal-install.cabal +++ b/cabal-install/cabal-install.cabal @@ -209,7 +209,6 @@ library async >= 2.0 && < 2.3, array >= 0.4 && < 0.6, base16-bytestring >= 0.1.1 && < 1.1.0.0, - base64-bytestring >= 1.0 && < 1.3, binary >= 0.7.3 && < 0.9, bytestring >= 0.10.6.0 && < 0.13, containers >= 0.5.6.2 && < 0.8, diff --git a/cabal-install/src/Distribution/Client/HashValue.hs b/cabal-install/src/Distribution/Client/HashValue.hs index c245750bb..e19956b7e 100644 --- a/cabal-install/src/Distribution/Client/HashValue.hs +++ b/cabal-install/src/Distribution/Client/HashValue.hs @@ -7,7 +7,6 @@ module Distribution.Client.HashValue , hashValue , truncateHash , showHashValue - , showHashValueBase64 , readFileHashValue , hashFromTUF ) where @@ -19,7 +18,6 @@ import qualified Hackage.Security.Client as Sec import qualified Crypto.Hash.SHA256 as SHA256 import qualified Data.ByteString.Base16 as Base16 -import qualified Data.ByteString.Base64 as Base64 import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy.Char8 as LBS @@ -57,9 +55,6 @@ hashValue = HashValue . SHA256.hashlazy showHashValue :: HashValue -> String showHashValue (HashValue digest) = BS.unpack (Base16.encode digest) -showHashValueBase64 :: HashValue -> String -showHashValueBase64 (HashValue digest) = BS.unpack (Base64.encode digest) - -- | Hash the content of a file. Uses SHA256. readFileHashValue :: FilePath -> IO HashValue readFileHashValue tarball = diff --git a/cabal-install/src/Distribution/Client/ScriptUtils.hs b/cabal-install/src/Distribution/Client/ScriptUtils.hs index eacf9cd5a..e66117414 100644 --- a/cabal-install/src/Distribution/Client/ScriptUtils.hs +++ b/cabal-install/src/Distribution/Client/ScriptUtils.hs @@ -37,7 +37,8 @@ import Distribution.Client.DistDirLayout ) import Distribution.Client.HashValue ( hashValue - , showHashValueBase64 + , showHashValue + , truncateHash ) import Distribution.Client.HttpUtils ( HttpTransport @@ -218,18 +219,15 @@ import qualified Text.Parsec as P -- repl to deal with the fact that the repl is relative to the working directory and not -- the project root. --- | Get the hash of a script's absolute path) +-- | Get the hash of a script's absolute path. -- -- Two hashes will be the same as long as the absolute paths -- are the same. getScriptHash :: FilePath -> IO String getScriptHash script = - -- Base64 is shorter than Base16, which helps avoid long path issues on windows - -- but it can contain /'s which aren't valid in file paths so replace them with - -- %'s. 26 chars / 130 bits is enough to practically avoid collisions. - map (\c -> if c == '/' then '%' else c) - . take 26 - . showHashValueBase64 + -- Truncation here tries to help with long path issues on Windows. + showHashValue + . truncateHash 26 . hashValue . fromString <$> canonicalizePath script diff --git a/cabal-testsuite/cabal-testsuite.cabal b/cabal-testsuite/cabal-testsuite.cabal index 55aa7921b..2fbac27d8 100644 --- a/cabal-testsuite/cabal-testsuite.cabal +++ b/cabal-testsuite/cabal-testsuite.cabal @@ -60,7 +60,7 @@ library , aeson ^>= 1.4.2.0 || ^>=1.5.0.0 || ^>= 2.0.0.0 || ^>= 2.1.0.0 || ^>= 2.2.1.0 , async ^>= 2.2.1 , attoparsec ^>= 0.13.2.2 || ^>=0.14.1 - , base64-bytestring ^>= 1.0.0.0 || ^>= 1.1.0.0 || ^>= 1.2.0.0 + , base16-bytestring ^>= 0.1.1.5 || ^>= 1.0 , bytestring ^>= 0.10.0.2 || ^>= 0.11.0.0 || ^>= 0.12.0.0 , containers ^>= 0.5.0.0 || ^>= 0.6.0.1 , cryptohash-sha256 ^>= 0.11.101.0 @@ -120,6 +120,7 @@ executable setup -- If you require an external dependency for a test it must be listed here. executable test-runtime-deps + default-language: Haskell2010 build-depends: cabal-testsuite, base, directory, diff --git a/cabal-testsuite/src/Test/Cabal/Prelude.hs b/cabal-testsuite/src/Test/Cabal/Prelude.hs index c95a55988..f8df47ec8 100644 --- a/cabal-testsuite/src/Test/Cabal/Prelude.hs +++ b/cabal-testsuite/src/Test/Cabal/Prelude.hs @@ -53,7 +53,7 @@ import Control.Monad (unless, when, void, forM_, liftM2, liftM4) import Control.Monad.Trans.Reader (withReaderT, runReaderT) import Control.Monad.IO.Class (MonadIO (..)) import qualified Crypto.Hash.SHA256 as SHA256 -import qualified Data.ByteString.Base64 as Base64 +import qualified Data.ByteString.Base16 as Base16 import qualified Data.ByteString.Char8 as C import Data.List (isInfixOf, stripPrefix, isPrefixOf, intercalate) import Data.List.NonEmpty (NonEmpty (..)) @@ -856,8 +856,7 @@ getScriptCacheDirectory :: FilePath -> TestM FilePath getScriptCacheDirectory script = do cabalDir <- testCabalDir `fmap` getTestEnv hashinput <- liftIO $ canonicalizePath script - let hash = map (\c -> if c == '/' then '%' else c) . take 26 - . C.unpack . Base64.encode . SHA256.hash . C.pack $ hashinput + let hash = C.unpack . Base16.encode . C.take 26 . SHA256.hash . C.pack $ hashinput return $ cabalDir "script-builds" hash ------------------------------------------------------------------------ diff --git a/changelog.d/base16-script-cache b/changelog.d/base16-script-cache new file mode 100644 index 000000000..b395f946a --- /dev/null +++ b/changelog.d/base16-script-cache @@ -0,0 +1,9 @@ +synopsis: Script cache dir is the base16 hash of the canonical path of the script. +prs: #9459 +packages: cabal-install + +description: { + +Script cache dir is the base16 hash of the canonical path of the script. + +} -- 2.11.4.GIT