From faa3c6a681d9c64916c7f8570c4a2e5bd774524f Mon Sep 17 00:00:00 2001 From: Matthew Pickering Date: Wed, 5 Mar 2025 16:06:22 +0000 Subject: [PATCH] Add module name validation in cabal check command This change ensures that Cabal warns about modules with names that would cause portability issues, especially on Windows systems where certain names like "aux", "con", "nul", etc. are reserved by the operating system. Fixes #10295 --- .../PackageDescription/Check/Paths.hs | 1 + .../PackageDescription/Check/Target.hs | 16 ++++++- .../InvalidModuleName/InvalidModuleName.cabal | 44 +++++++++++++++++++ .../Check/InvalidModuleName/LICENSE | 0 .../Check/InvalidModuleName/bench/.file | 0 .../Check/InvalidModuleName/cabal.out | 10 +++++ .../Check/InvalidModuleName/cabal.test.hs | 5 +++ .../Check/InvalidModuleName/exe/.file | 0 .../Check/InvalidModuleName/src/.file | 0 .../Check/InvalidModuleName/test/.file | 0 changelog.d/pr-10816.md | 23 ++++++++++ 11 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 cabal-testsuite/PackageTests/Check/InvalidModuleName/InvalidModuleName.cabal create mode 100644 cabal-testsuite/PackageTests/Check/InvalidModuleName/LICENSE create mode 100644 cabal-testsuite/PackageTests/Check/InvalidModuleName/bench/.file create mode 100644 cabal-testsuite/PackageTests/Check/InvalidModuleName/cabal.out create mode 100644 cabal-testsuite/PackageTests/Check/InvalidModuleName/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/Check/InvalidModuleName/exe/.file create mode 100644 cabal-testsuite/PackageTests/Check/InvalidModuleName/src/.file create mode 100644 cabal-testsuite/PackageTests/Check/InvalidModuleName/test/.file create mode 100644 changelog.d/pr-10816.md diff --git a/Cabal/src/Distribution/PackageDescription/Check/Paths.hs b/Cabal/src/Distribution/PackageDescription/Check/Paths.hs index 5b2df1f18fa..28e1e3815e2 100644 --- a/Cabal/src/Distribution/PackageDescription/Check/Paths.hs +++ b/Cabal/src/Distribution/PackageDescription/Check/Paths.hs @@ -10,6 +10,7 @@ module Distribution.PackageDescription.Check.Paths ( checkGlob , checkPath + , checkPackageFileNamesWithGlob , fileExtensionSupportedLanguage , isGoodRelativeDirectoryPath , isGoodRelativeFilePath diff --git a/Cabal/src/Distribution/PackageDescription/Check/Target.hs b/Cabal/src/Distribution/PackageDescription/Check/Target.hs index 0bf173cb980..9e23b0af917 100644 --- a/Cabal/src/Distribution/PackageDescription/Check/Target.hs +++ b/Cabal/src/Distribution/PackageDescription/Check/Target.hs @@ -21,7 +21,7 @@ import Prelude () import Distribution.CabalSpecVersion import Distribution.Compat.Lens import Distribution.Compiler -import Distribution.ModuleName (ModuleName) +import Distribution.ModuleName (ModuleName, toFilePath) import Distribution.Package import Distribution.PackageDescription import Distribution.PackageDescription.Check.Common @@ -61,6 +61,8 @@ checkLibrary _libVisibility_ libBuildInfo_ ) = do + mapM_ checkModuleName (explicitLibModules lib) + checkP (libName_ == LMainLibName && isSub) (PackageBuildImpossible UnnamedInternal) @@ -144,6 +146,8 @@ checkExecutable let cet = CETExecutable exeName_ modulePath_ = getSymbolicPath symbolicModulePath_ + mapM_ checkModuleName (exeModules exe) + -- § Exe specific checks checkP (null modulePath_) @@ -205,6 +209,9 @@ checkTestSuite TestSuiteUnsupported tt -> tellP (PackageBuildWarning $ TestsuiteNotSupported tt) _ -> return () + + mapM_ checkModuleName (testModules ts) + checkP mainIsWrongExt (PackageBuildImpossible NoHsLhsMain) @@ -257,6 +264,8 @@ checkBenchmark -- Target type/name (benchmark). let cet = CETBenchmark benchmarkName_ + mapM_ checkModuleName (benchmarkModules bm) + -- § Interface & bm specific tests. case benchmarkInterface_ of BenchmarkUnsupported tt@(BenchmarkTypeUnknown _ _) -> @@ -294,6 +303,11 @@ checkBenchmark BenchmarkExeV10 _ f -> takeExtension (getSymbolicPath f) `notElem` [".hs", ".lhs"] _ -> False +-- | Check if a module name is valid on both Windows and Posix systems +checkModuleName :: Monad m => ModuleName -> CheckM m () +checkModuleName moduleName = + checkPackageFileNamesWithGlob PathKindFile (toFilePath moduleName) + -- ------------------------------------------------------------ -- Build info -- ------------------------------------------------------------ diff --git a/cabal-testsuite/PackageTests/Check/InvalidModuleName/InvalidModuleName.cabal b/cabal-testsuite/PackageTests/Check/InvalidModuleName/InvalidModuleName.cabal new file mode 100644 index 00000000000..e298eece9b6 --- /dev/null +++ b/cabal-testsuite/PackageTests/Check/InvalidModuleName/InvalidModuleName.cabal @@ -0,0 +1,44 @@ +name: InvalidModuleName +version: 0.1.0.0 +license: BSD3 +license-file: LICENSE +category: development +author: Foo Bar +maintainer: cabal-dev@haskell.org +build-type: Simple +cabal-version: >=1.10 +synopsis: Test for invalid module names +description: Tests that invalid module names are properly rejected by cabal check + +library + exposed-modules: Aux + build-depends: base < 5 + hs-source-dirs: src + default-language: Haskell2010 + +executable invalid-exe + main-is: Main.hs + other-modules: Exe.Aux + , Exe.Aux.Test + build-depends: base < 5 + hs-source-dirs: exe + default-language: Haskell2010 + +test-suite invalid-test + type: exitcode-stdio-1.0 + main-is: Main.hs + other-modules: Test.Aux + , Test.Aux.Test + build-depends: base < 5 + hs-source-dirs: test + default-language: Haskell2010 + +benchmark invalid-bench + type: exitcode-stdio-1.0 + main-is: Main.hs + other-modules: Bench.Aux + , Bench.Aux.Test + build-depends: base < 5 + hs-source-dirs: bench + default-language: Haskell2010 + diff --git a/cabal-testsuite/PackageTests/Check/InvalidModuleName/LICENSE b/cabal-testsuite/PackageTests/Check/InvalidModuleName/LICENSE new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cabal-testsuite/PackageTests/Check/InvalidModuleName/bench/.file b/cabal-testsuite/PackageTests/Check/InvalidModuleName/bench/.file new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cabal-testsuite/PackageTests/Check/InvalidModuleName/cabal.out b/cabal-testsuite/PackageTests/Check/InvalidModuleName/cabal.out new file mode 100644 index 00000000000..3093fce3d24 --- /dev/null +++ b/cabal-testsuite/PackageTests/Check/InvalidModuleName/cabal.out @@ -0,0 +1,10 @@ +# cabal check +The following errors will cause portability problems on other environments: +Error: [invalid-path-win] The path 'Aux' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$". +Error: [invalid-path-win] The path 'Bench/Aux' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$". +Error: [invalid-path-win] The path 'Bench/Aux/Test' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$". +Error: [invalid-path-win] The path 'Exe/Aux' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$". +Error: [invalid-path-win] The path 'Exe/Aux/Test' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$". +Error: [invalid-path-win] The path 'Test/Aux' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$". +Error: [invalid-path-win] The path 'Test/Aux/Test' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$". +Error: Hackage would reject this package. diff --git a/cabal-testsuite/PackageTests/Check/InvalidModuleName/cabal.test.hs b/cabal-testsuite/PackageTests/Check/InvalidModuleName/cabal.test.hs new file mode 100644 index 00000000000..8756cdecc85 --- /dev/null +++ b/cabal-testsuite/PackageTests/Check/InvalidModuleName/cabal.test.hs @@ -0,0 +1,5 @@ +import Test.Cabal.Prelude + +main = cabalTest $ + fails $ cabal "check" [] + diff --git a/cabal-testsuite/PackageTests/Check/InvalidModuleName/exe/.file b/cabal-testsuite/PackageTests/Check/InvalidModuleName/exe/.file new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cabal-testsuite/PackageTests/Check/InvalidModuleName/src/.file b/cabal-testsuite/PackageTests/Check/InvalidModuleName/src/.file new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cabal-testsuite/PackageTests/Check/InvalidModuleName/test/.file b/cabal-testsuite/PackageTests/Check/InvalidModuleName/test/.file new file mode 100644 index 00000000000..e69de29bb2d diff --git a/changelog.d/pr-10816.md b/changelog.d/pr-10816.md new file mode 100644 index 00000000000..06118ecbb5b --- /dev/null +++ b/changelog.d/pr-10816.md @@ -0,0 +1,23 @@ +synopsis: "Add checks for Windows reserved filenames in module paths" +packages: Cabal cabal-install +prs: #10816 +issues: #10295 + +description: { + +On Windows, certain filenames are reserved by the operating system such as +"aux", "con", "prn", "nul", etc. When these names appear in module paths they +can cause build failures on Windows systems. + +`cabal check` now properly warns about module paths that contain Windows reserved +filenames, not just filepaths which contain these reserved tokens. These warnings +are controlled by the existing `invalid-win-path` category. + +For example, module paths like: +- `Exe.Aux.Test` +- `Test.Aux.Module` +- `Bench.Aux.Helpers` + +will now trigger appropriate warnings during `cabal check`. + +}