Hello,
I am investigating if and how hie files could be used for a cabal-audit command to check what are the declarations being used from the build dependencies. The use-case would be to alert the user when a vulnerable function is being used. This would be particularly important to avoid false alarm when a given vulnerability only appears in a rarely used declaration of a popular package.
So far, I’ve implemented the following function (code) which seems to work well for simple terms:
-- | Returns all the edges between a top level declaration and its dependencies.
getDependencies :: HieFile -> [(TopLevelDeclaration, Declaration)]
For example, given the following modules:
module CabalAudit.Test.Class where
class TestClass a where
  tasty :: a -> Bool
module CabalAudit.Test.Instance where
import CabalAudit.Test.Class
data Tea = Tea
instance TestClass Tea where
  tasty = not . alwaysTrue
instance Show Tea where
  show Tea = "thè" ++ "!"
alwaysTrue :: Tea -> Bool
alwaysTrue = const True
module CabalAudit.Test.User where
import CabalAudit.Test.Class
import CabalAudit.Test.Instance
useAlwaysTrue :: Bool
useAlwaysTrue = tasty Tea
Here is the current output of the tool:
# CabalAudit.Test.Instance
GHC.Show.show: GHC.Base.++, CabalAudit.Test.Instance.Tea
CabalAudit.Test.Class.tasty: GHC.Base.., GHC.Classes.not, CabalAudit.Test.Instance.alwaysTrue, GHC.Base.const, GHC.Types.True
CabalAudit.Test.Instance.alwaysTrue: GHC.Base.const, GHC.Types.True
# CabalAudit.Test.User
CabalAudit.Test.User.useAlwaysTrue: CabalAudit.Test.Class.tasty, GHC.Base.., GHC.Classes.not, CabalAudit.Test.Instance.alwaysTrue, GHC.Base.const, GHC.Types.True, CabalAudit.Test.Instance.Tea
This looks promising, we can see that alwaysTrue is reachable from the useAlwaysTrue declaration. However, I don’t know why the class instances are not attached to the local module (e.g. CabalAudit.Test.Class.Show of Tea instead of GHC.Show.show).
Before continuing down that path, I would appreciate some feedbacks on this strategy, in particular:
- Is this a good usage of hie files? It seems like we would need to rebuild the dependencies with -fwrite-ide-info, so perhaps we could also use a GHC plugin, would that be better?
- How to handle typeclass correctly, do we need to use generateReferencesMap?
- Beside typeclass instances, what other pitfalls would need to be addressed, e.g. are TypeFamilies going to be an issue?
Thank you for your time,
-Tristan

