dhscanner-bitcode 2.3.0 → 2.4.0
raw patch · 3 files changed
+393/−390 lines, 3 filesdep ~dhscanner-astPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: dhscanner-ast
API changes (from Hackage documentation)
- Callable: Annotation :: Location -> Annotation
- Callable: data Annotation
- Callable: instance Data.Aeson.Types.FromJSON.FromJSON Callable.Annotation
- Callable: instance Data.Aeson.Types.ToJSON.ToJSON Callable.Annotation
- Callable: instance GHC.Internal.Classes.Eq Callable.Annotation
- Callable: instance GHC.Internal.Classes.Ord Callable.Annotation
- Callable: instance GHC.Internal.Generics.Generic Callable.Annotation
- Callable: instance GHC.Internal.Show.Show Callable.Annotation
+ Bitcode: Annotation :: Location -> Annotation
+ Bitcode: [paramAnnotations] :: ParamDeclContent -> [Annotation]
+ Bitcode: data Annotation
+ Bitcode: instance Data.Aeson.Types.FromJSON.FromJSON Bitcode.Annotation
+ Bitcode: instance Data.Aeson.Types.ToJSON.ToJSON Bitcode.Annotation
+ Bitcode: instance GHC.Internal.Classes.Eq Bitcode.Annotation
+ Bitcode: instance GHC.Internal.Classes.Ord Bitcode.Annotation
+ Bitcode: instance GHC.Internal.Generics.Generic Bitcode.Annotation
+ Bitcode: instance GHC.Internal.Show.Show Bitcode.Annotation
- Bitcode: ParamDeclContent :: ParamVariable -> ParamDeclContent
+ Bitcode: ParamDeclContent :: ParamVariable -> [Annotation] -> ParamDeclContent
Files
- dhscanner-bitcode.cabal +2/−2
- src/Bitcode.hs +280/−274
- src/Callable.hs +111/−114
dhscanner-bitcode.cabal view
@@ -20,7 +20,7 @@ in mind. The commands resemble an abstract RISC-style assembley, motivated by keeping later-phases analyses as simple as possible. -version: 2.3.0 +version: 2.4.0 license: GPL-3.0-only license-file: LICENSE author: OrenGitHub @@ -48,7 +48,7 @@ aeson >= 2.2 && < 2.4, base >= 4.22 && < 4.23, containers >= 0.8 && < 0.9, - dhscanner-ast >= 1.5.0 && < 1.6 + dhscanner-ast >= 1.6.0 hs-source-dirs: src
src/Bitcode.hs view
@@ -1,274 +1,280 @@--- | --- --- * The [intermediate language (IL) \/ intermediate representation (IR) \/ bitcode](https://en.wikipedia.org/wiki/Intermediate_representation#Intermediate_language) --- are all synonyms for: --- --- * a data structure able to represent code originating from /multiple/ programming languages. --- * minimal instruction set, similar in spirit to [RISC](https://en.wikipedia.org/wiki/Reduced_instruction_set_computer) architectures --- * unlike /actual/ assembly, it has an /infinite/ number of temporaries ( instead of registers ) --- --- * Its main purpose is to serve as the: --- --- * second step for /static code analysis/ --- * part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework for --- static analysis performing security checks 🔒 and --- [PII](https://en.wikipedia.org/wiki/Personal_data) leaks detection 🪪 --- --- * As part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework: --- --- * targets mostly languages used for /cloud native applications/ ☁️ --- * Python, Ruby 💎, Php, Javascript, Typescript, Java ☕️, C# and Golang. --- --- * Typical flow: --- --- * Abstract syntax trees (ASTs) are scanned --- --- * 'Callable' entities are identified --- * each 'Callable' is associated with its control flow graph ('Cfg') --- * control flow graphs are directed, connecting bitcode instructions --- --- * Non Haskell parogrammers note: --- --- * Each 'Callable' object is /immutable/ ( like everything else in Haskell ... ) --- - -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE OverloadedStrings #-} - -module Bitcode - -where - --- project imports -import Fqn -import Location -import qualified Token - --- general imports -import GHC.Generics -import Data.Aeson ( ToJSON, FromJSON ) - --- | --- * All instructions have an associated location --- --- * That is also true for instrumented instructions (like `Nop` and `Assume`) --- -data Instruction - = Instruction - { - location :: Location, - instructionContent :: InstructionContent - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - --- | --- A minimal instruction set for translating common programming languages -data InstructionContent - = Nop - | Call CallContent - | Unop UnopContent - | Binop BinopContent - | Assume AssumeContent - | Return ReturnContent - | Assign AssignContent - | ParamDecl ParamDeclContent - | FieldRead FieldReadContent - | FieldWrite FieldWriteContent - | UnresolvedRef UnresolvedRefContent -- ^ @since 1.0.5 - | SubscriptRead SubscriptReadContent - | SubscriptWrite SubscriptWriteContent - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data Value - = VariableCtor Variable - | ConstValueCtor ConstValue - | KeywordArgCtor KeywordArgVariable - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data Variable - = TmpVariableCtor TmpVariable - | SrcVariableCtor SrcVariable - | ParamVariableCtor ParamVariable - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data TmpVariable - = TmpVariable - { - tmpVariableFqn :: Fqn, - tmpVariableLocation :: Location - } - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data SrcVariable - = SrcVariable - { - srcVariableFqn :: Fqn, - srcVariableToken :: Token.VarName - } - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data ParamVariable - = ParamVariable - { - paramVariableFqn :: Fqn, - paramVariableSerialIdx :: Word, -- ^ zero-based - paramVariableToken :: Token.ParamName - } - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data KeywordArgVariable - = KeywordArgVariable - { - keywordArgName :: String, - keywordArgValue :: Value - } - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -variableFqn :: Variable -> Fqn -variableFqn (TmpVariableCtor (TmpVariable fqn _ )) = fqn -variableFqn (SrcVariableCtor (SrcVariable fqn _ )) = fqn -variableFqn (ParamVariableCtor (ParamVariable fqn _ _ )) = fqn - -locationVariable :: Variable -> Location -locationVariable (TmpVariableCtor t) = tmpVariableLocation t -locationVariable (SrcVariableCtor s) = Token.getVarNameLocation (srcVariableToken s) -locationVariable (ParamVariableCtor p) = Token.getParamNameLocation (paramVariableToken p) - -locationValue :: Value -> Location -locationValue (VariableCtor v) = locationVariable v -locationValue (ConstValueCtor c) = locationConstValue c -locationValue (KeywordArgCtor k) = locationValue (keywordArgValue k) - -locationConstValue :: ConstValue -> Location -locationConstValue (ConstIntValue i) = Token.constIntLocation i -locationConstValue (ConstStrValue s) = Token.constStrLocation s -locationConstValue (ConstBoolValue b) = Token.constBoolLocation b -locationConstValue (ConstNullValue n) = Token.constNullLocation n - -data CallContent - = CallContent - { - callOutput :: Variable, - callee :: Variable, - args :: [ Value ], - callLocation :: Location - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data UnresolvedRefContent - = UnresolvedRefContent - { - unresolvedRefOutput :: Variable, - unresolvedRef :: Variable, - unresolvedRefLocation :: Location - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - --- | Coarse operator classification for 'BinopContent'. Only equality --- variants are distinguished; everything else collapses to 'OtherOp' so --- downstream analyses ( e.g. @kb_comparison@ in @dhscanner-kbgen@ ) can --- pick out gated-return-on-comparison patterns without carrying the full --- 'Ast.Operator' surface into the bitcode layer. -data BinopOp - = EqOp - | NeqOp - | OtherOp - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data BinopContent - = BinopContent - { - binopOutput :: Variable, - binopLhs :: Value, - binopRhs :: Value, - binopOperator :: BinopOp - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data UnopContent - = UnopContent - { - unopOutput :: Variable, - unopLhs :: Value - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data AssumeContent - = AssumeContent - { - assumeValue :: Value, - assumeTruthy :: Bool - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -mkNopInstruction :: Location -> Instruction -mkNopInstruction l = Instruction { location = l, instructionContent = Nop } - -mkAssumeInstruction :: Value -> Bool -> Instruction -mkAssumeInstruction v b = Instruction (locationValue v) (Assume (AssumeContent v b)) - -data ReturnContent - = ReturnContent - { - returnValue :: Maybe Value - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data AssignContent - = AssignContent - { - assignOutput :: Variable, - assignInput :: Value - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data ConstValue - = ConstIntValue Token.ConstInt - | ConstStrValue Token.ConstStr - | ConstBoolValue Token.ConstBool - | ConstNullValue Token.ConstNull - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data FieldReadContent - = FieldReadContent - { - fieldReadOutput :: Variable, - fieldReadInput :: Variable, - fieldReadName :: Token.FieldName - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data FieldWriteContent - = FieldWriteContent - { - fieldWriteOutput :: Variable, - fieldWriteName :: Token.FieldName, - fieldWriteInput :: Value - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data SubscriptReadContent - = SubscriptReadContent - { - subscriptReadOutput :: Variable, - subscriptReadInput :: Variable, - subscriptReadIdx :: Value - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data SubscriptWriteContent - = SubscriptWriteContent - { - subscriptWriteOutput :: Variable, - subscriptWriteIdx :: Value, - subscriptWriteInput :: Value - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) - -data ParamDeclContent - = ParamDeclContent - { - paramVariable :: ParamVariable - } - deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord ) +-- |+--+-- * The [intermediate language (IL) \/ intermediate representation (IR) \/ bitcode](https://en.wikipedia.org/wiki/Intermediate_representation#Intermediate_language)+-- are all synonyms for:+--+-- * a data structure able to represent code originating from /multiple/ programming languages.+-- * minimal instruction set, similar in spirit to [RISC](https://en.wikipedia.org/wiki/Reduced_instruction_set_computer) architectures+-- * unlike /actual/ assembly, it has an /infinite/ number of temporaries ( instead of registers )+--+-- * Its main purpose is to serve as the:+--+-- * second step for /static code analysis/ +-- * part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework for+-- static analysis performing security checks 🔒 and+-- [PII](https://en.wikipedia.org/wiki/Personal_data) leaks detection 🪪+--+-- * As part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework:+--+-- * targets mostly languages used for /cloud native applications/ ☁️+-- * Python, Ruby 💎, Php, Javascript, Typescript, Java ☕️, C# and Golang.+--+-- * Typical flow:+--+-- * Abstract syntax trees (ASTs) are scanned+--+-- * 'Callable' entities are identified+-- * each 'Callable' is associated with its control flow graph ('Cfg')+-- * control flow graphs are directed, connecting bitcode instructions+--+-- * Non Haskell parogrammers note:+--+-- * Each 'Callable' object is /immutable/ ( like everything else in Haskell ... )+--++{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE OverloadedStrings #-}++module Bitcode++where++-- project imports+import Fqn+import Location+import qualified Token++-- general imports+import GHC.Generics+import Data.Aeson ( ToJSON, FromJSON )++-- |+-- * All instructions have an associated location+--+-- * That is also true for instrumented instructions (like `Nop` and `Assume`)+--+data Instruction+ = Instruction+ {+ location :: Location,+ instructionContent :: InstructionContent+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++-- |+-- A minimal instruction set for translating common programming languages+data InstructionContent+ = Nop+ | Call CallContent+ | Unop UnopContent+ | Binop BinopContent+ | Assume AssumeContent+ | Return ReturnContent+ | Assign AssignContent+ | ParamDecl ParamDeclContent+ | FieldRead FieldReadContent+ | FieldWrite FieldWriteContent+ | UnresolvedRef UnresolvedRefContent -- ^ @since 1.0.5+ | SubscriptRead SubscriptReadContent+ | SubscriptWrite SubscriptWriteContent+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data Value+ = VariableCtor Variable+ | ConstValueCtor ConstValue+ | KeywordArgCtor KeywordArgVariable+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data Variable+ = TmpVariableCtor TmpVariable+ | SrcVariableCtor SrcVariable+ | ParamVariableCtor ParamVariable+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data TmpVariable+ = TmpVariable+ {+ tmpVariableFqn :: Fqn,+ tmpVariableLocation :: Location+ }+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data SrcVariable+ = SrcVariable+ {+ srcVariableFqn :: Fqn,+ srcVariableToken :: Token.VarName+ }+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data ParamVariable+ = ParamVariable+ {+ paramVariableFqn :: Fqn,+ paramVariableSerialIdx :: Word, -- ^ zero-based+ paramVariableToken :: Token.ParamName+ }+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data KeywordArgVariable+ = KeywordArgVariable+ {+ keywordArgName :: String,+ keywordArgValue :: Value+ }+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++variableFqn :: Variable -> Fqn+variableFqn (TmpVariableCtor (TmpVariable fqn _ )) = fqn+variableFqn (SrcVariableCtor (SrcVariable fqn _ )) = fqn+variableFqn (ParamVariableCtor (ParamVariable fqn _ _ )) = fqn++locationVariable :: Variable -> Location+locationVariable (TmpVariableCtor t) = tmpVariableLocation t+locationVariable (SrcVariableCtor s) = Token.getVarNameLocation (srcVariableToken s)+locationVariable (ParamVariableCtor p) = Token.getParamNameLocation (paramVariableToken p)++locationValue :: Value -> Location+locationValue (VariableCtor v) = locationVariable v+locationValue (ConstValueCtor c) = locationConstValue c+locationValue (KeywordArgCtor k) = locationValue (keywordArgValue k)++locationConstValue :: ConstValue -> Location+locationConstValue (ConstIntValue i) = Token.constIntLocation i+locationConstValue (ConstStrValue s) = Token.constStrLocation s+locationConstValue (ConstBoolValue b) = Token.constBoolLocation b+locationConstValue (ConstNullValue n) = Token.constNullLocation n++data CallContent+ = CallContent+ {+ callOutput :: Variable,+ callee :: Variable,+ args :: [ Value ],+ callLocation :: Location+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data UnresolvedRefContent+ = UnresolvedRefContent+ {+ unresolvedRefOutput :: Variable,+ unresolvedRef :: Variable,+ unresolvedRefLocation :: Location+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++-- | Coarse operator classification for 'BinopContent'. Only equality+-- variants are distinguished; everything else collapses to 'OtherOp' so+-- downstream analyses ( e.g. @kb_comparison@ in @dhscanner-kbgen@ ) can+-- pick out gated-return-on-comparison patterns without carrying the full+-- 'Ast.Operator' surface into the bitcode layer.+data BinopOp+ = EqOp+ | NeqOp+ | OtherOp+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data BinopContent+ = BinopContent+ {+ binopOutput :: Variable,+ binopLhs :: Value,+ binopRhs :: Value,+ binopOperator :: BinopOp+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data UnopContent+ = UnopContent+ {+ unopOutput :: Variable,+ unopLhs :: Value+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data AssumeContent+ = AssumeContent+ {+ assumeValue :: Value,+ assumeTruthy :: Bool+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++mkNopInstruction :: Location -> Instruction+mkNopInstruction l = Instruction { location = l, instructionContent = Nop }++mkAssumeInstruction :: Value -> Bool -> Instruction+mkAssumeInstruction v b = Instruction (locationValue v) (Assume (AssumeContent v b))++data ReturnContent+ = ReturnContent+ {+ returnValue :: Maybe Value+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data AssignContent+ = AssignContent+ {+ assignOutput :: Variable,+ assignInput :: Value+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data ConstValue+ = ConstIntValue Token.ConstInt+ | ConstStrValue Token.ConstStr+ | ConstBoolValue Token.ConstBool+ | ConstNullValue Token.ConstNull+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data FieldReadContent+ = FieldReadContent+ {+ fieldReadOutput :: Variable,+ fieldReadInput :: Variable,+ fieldReadName :: Token.FieldName+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data FieldWriteContent+ = FieldWriteContent+ {+ fieldWriteOutput :: Variable,+ fieldWriteName :: Token.FieldName,+ fieldWriteInput :: Value+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data SubscriptReadContent+ = SubscriptReadContent+ {+ subscriptReadOutput :: Variable,+ subscriptReadInput :: Variable,+ subscriptReadIdx :: Value+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data SubscriptWriteContent+ = SubscriptWriteContent+ {+ subscriptWriteOutput :: Variable,+ subscriptWriteIdx :: Value,+ subscriptWriteInput :: Value+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++data ParamDeclContent+ = ParamDeclContent+ {+ paramVariable :: ParamVariable,+ paramAnnotations :: [ Annotation ] -- ^ ( for example, Java Spring: @\@RequestParam@ )+ }+ deriving ( Show, Eq, Generic, ToJSON, FromJSON, Ord )++-- | an annotation ( java @GetMapping, python decorator, ... ) is just its+-- location : it is lowered as a call at that same location, so its fqn+-- and args come from the call+data Annotation = Annotation Location deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )
src/Callable.hs view
@@ -1,114 +1,111 @@--- | --- --- * The [intermediate language (IL) \/ intermediate representation (IR) \/ bitcode](https://en.wikipedia.org/wiki/Intermediate_representation#Intermediate_language) --- are all synonyms for a data structure able to represent code originating from /multiple/ --- programming languages. --- --- * In our context, the main purpose is to enable an efficient and uniform /static code analysis/, --- as part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework --- for [CI/CD](https://en.wikipedia.org/wiki/CI/CD) container security checks. --- --- * [dhscanner](https://github.com/OrenGitHub/dhscanner) targets mostly languages used for /cloud native applications/: --- __Python__, __Ruby__, __Php__, __Javascript__, __Typescript__, __Java__, __C#__ and __Golang__. --- --- * Typically, a collection of files are first parsed using relevant --- [parsers](https://github.com/OrenGitHub/dhscanner.1.parsers), then, --- the resulting abstract syntax trees are sent to code generation, --- where they are translated into a collection of /callables/. --- --- * A callable is a sequence of commands corresponding to either a function, a method, --- a lambda or (in languages like python) a script. --- - -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE OverloadedStrings #-} - -module Callable - -where - --- project imports -import Cfg -import Fqn -import Token -import Location - --- general imports -import Data.Aeson -import GHC.Generics - -data Callables - = Callables - { - actualCallables :: [ Callable ] - } - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - --- | Four kinds of callables. -data Callable - = Method MethodContent - | Lambda LambdaContent - | Script ScriptContent - | Function FunctionContent - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data HostingClassSuper - = HostingClassSuper - { - hostingClassSuperName :: Token.SuperName, - hostingClassSuperResolvedType :: Maybe Fqn - } - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data MethodContent - = MethodContent - { - methodName :: Token.MethodName, - hostingClassName :: Token.ClassName, - hostingClassSupers :: [ HostingClassSuper ], - hostingClassAnnotations :: [ Annotation ], - methodBody :: Cfg, - methodAnnotations :: [ Annotation ], - methodLocation :: Location, - methodSourceBodyLength :: Word -- ^ number of source-level statements ( see @stmtMethodBody@ in "Ast" ) - } - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data LambdaContent - = LambdaContent - { - lambdaBody :: Cfg, - lambdaLocation :: Location, - lambdaSourceBodyLength :: Word -- ^ number of source-level statements ( see @expLambdaBody@ in "Ast" ) - } - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data ScriptContent - = ScriptContent - { - filename :: String, - scriptBody :: Cfg - } - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data Annotation = Annotation Location deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - -data FunctionContent - = FunctionContent - { - funcName :: Token.FuncName, - funcBody :: Cfg, - funcAnnotations :: [ Annotation ], - funcLocation :: Location, - funcSourceBodyLength :: Word -- ^ number of source-level statements ( see @stmtFuncBody@ in "Ast" ) - } - deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) - --- | Number of source-level statements in the callable's body ( see "Ast" ). Returns @0@ for 'Script'. -numOriginalSourceInstructions :: Callable -> Word -numOriginalSourceInstructions (Method m) = methodSourceBodyLength m -numOriginalSourceInstructions (Lambda l) = lambdaSourceBodyLength l -numOriginalSourceInstructions (Function f) = funcSourceBodyLength f -numOriginalSourceInstructions (Script _) = 0 - +-- |+--+-- * The [intermediate language (IL) \/ intermediate representation (IR) \/ bitcode](https://en.wikipedia.org/wiki/Intermediate_representation#Intermediate_language)+-- are all synonyms for a data structure able to represent code originating from /multiple/+-- programming languages.+--+-- * In our context, the main purpose is to enable an efficient and uniform /static code analysis/,+-- as part of the [dhscanner](https://github.com/OrenGitHub/dhscanner) framework+-- for [CI/CD](https://en.wikipedia.org/wiki/CI/CD) container security checks.+--+-- * [dhscanner](https://github.com/OrenGitHub/dhscanner) targets mostly languages used for /cloud native applications/:+-- __Python__, __Ruby__, __Php__, __Javascript__, __Typescript__, __Java__, __C#__ and __Golang__.+--+-- * Typically, a collection of files are first parsed using relevant+-- [parsers](https://github.com/OrenGitHub/dhscanner.1.parsers), then,+-- the resulting abstract syntax trees are sent to code generation,+-- where they are translated into a collection of /callables/.+--+-- * A callable is a sequence of commands corresponding to either a function, a method,+-- a lambda or (in languages like python) a script.+--++{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE OverloadedStrings #-}++module Callable where++-- project imports+import Bitcode+import Cfg+import Fqn+import Token+import Location++-- general imports+import Data.Aeson+import GHC.Generics++data Callables+ = Callables+ {+ actualCallables :: [ Callable ]+ }+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++-- | Four kinds of callables.+data Callable+ = Method MethodContent+ | Lambda LambdaContent+ | Script ScriptContent+ | Function FunctionContent+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data HostingClassSuper+ = HostingClassSuper+ {+ hostingClassSuperName :: Token.SuperName,+ hostingClassSuperResolvedType :: Maybe Fqn+ }+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data MethodContent+ = MethodContent+ {+ methodName :: Token.MethodName,+ hostingClassName :: Token.ClassName,+ hostingClassSupers :: [ HostingClassSuper ],+ hostingClassAnnotations :: [ Annotation ],+ methodBody :: Cfg,+ methodAnnotations :: [ Annotation ],+ methodLocation :: Location,+ methodSourceBodyLength :: Word -- ^ number of source-level statements ( see @stmtMethodBody@ in "Ast" )+ }+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data LambdaContent+ = LambdaContent+ {+ lambdaBody :: Cfg,+ lambdaLocation :: Location,+ lambdaSourceBodyLength :: Word -- ^ number of source-level statements ( see @expLambdaBody@ in "Ast" )+ }+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data ScriptContent+ = ScriptContent+ {+ filename :: String,+ scriptBody :: Cfg+ }+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++data FunctionContent+ = FunctionContent+ {+ funcName :: Token.FuncName,+ funcBody :: Cfg,+ funcAnnotations :: [ Annotation ],+ funcLocation :: Location,+ funcSourceBodyLength :: Word -- ^ number of source-level statements ( see @stmtFuncBody@ in "Ast" )+ }+ deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON )++-- | Number of source-level statements in the callable's body ( see "Ast" ). Returns @0@ for 'Script'.+numOriginalSourceInstructions :: Callable -> Word+numOriginalSourceInstructions (Method m) = methodSourceBodyLength m+numOriginalSourceInstructions (Lambda l) = lambdaSourceBodyLength l+numOriginalSourceInstructions (Function f) = funcSourceBodyLength f+numOriginalSourceInstructions (Script _) = 0+