dhscanner-kbgen 1.0.37 → 1.1.0
raw patch · 3 files changed
+134/−4 lines, 3 filesdep ~dhscanner-bitcodePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: dhscanner-bitcode
API changes (from Hackage documentation)
+ Kbgen: Cond :: Location -> Cond
+ Kbgen: ConstNull :: Location -> ConstNull
+ Kbgen: ConstNullCtor :: ConstNull -> Fact
+ Kbgen: GatedReturn :: Cond -> ReturnedValue -> GatedReturn
+ Kbgen: GatedReturnCtor :: GatedReturn -> Fact
+ Kbgen: ReturnedValue :: Location -> ReturnedValue
+ Kbgen: data Cond
+ Kbgen: data ConstNull
+ Kbgen: data GatedReturn
+ Kbgen: data ReturnedValue
+ Kbgen: instance Data.Aeson.Types.FromJSON.FromJSON Kbgen.Cond
+ Kbgen: instance Data.Aeson.Types.FromJSON.FromJSON Kbgen.ConstNull
+ Kbgen: instance Data.Aeson.Types.FromJSON.FromJSON Kbgen.GatedReturn
+ Kbgen: instance Data.Aeson.Types.FromJSON.FromJSON Kbgen.ReturnedValue
+ Kbgen: instance Data.Aeson.Types.ToJSON.ToJSON Kbgen.Cond
+ Kbgen: instance Data.Aeson.Types.ToJSON.ToJSON Kbgen.ConstNull
+ Kbgen: instance Data.Aeson.Types.ToJSON.ToJSON Kbgen.GatedReturn
+ Kbgen: instance Data.Aeson.Types.ToJSON.ToJSON Kbgen.ReturnedValue
+ Kbgen: instance GHC.Classes.Eq Kbgen.Cond
+ Kbgen: instance GHC.Classes.Eq Kbgen.ConstNull
+ Kbgen: instance GHC.Classes.Eq Kbgen.GatedReturn
+ Kbgen: instance GHC.Classes.Eq Kbgen.ReturnedValue
+ Kbgen: instance GHC.Classes.Ord Kbgen.Cond
+ Kbgen: instance GHC.Classes.Ord Kbgen.ConstNull
+ Kbgen: instance GHC.Classes.Ord Kbgen.GatedReturn
+ Kbgen: instance GHC.Classes.Ord Kbgen.ReturnedValue
+ Kbgen: instance GHC.Generics.Generic Kbgen.Cond
+ Kbgen: instance GHC.Generics.Generic Kbgen.ConstNull
+ Kbgen: instance GHC.Generics.Generic Kbgen.GatedReturn
+ Kbgen: instance GHC.Generics.Generic Kbgen.ReturnedValue
+ Kbgen: instance GHC.Show.Show Kbgen.Cond
+ Kbgen: instance GHC.Show.Show Kbgen.ConstNull
+ Kbgen: instance GHC.Show.Show Kbgen.GatedReturn
+ Kbgen: instance GHC.Show.Show Kbgen.ReturnedValue
Files
- dhscanner-kbgen.cabal +2/−2
- src/Kbgen.hs +95/−1
- test/SmokeTests.hs +37/−1
dhscanner-kbgen.cabal view
@@ -33,7 +33,7 @@ * explain in plain English your query's purpose * et voilà ! -version: 1.0.37 +version: 1.1.0 license: GPL-3.0-only license-file: LICENSE author: OrenGitHub @@ -63,7 +63,7 @@ containers < 0.7, text, dhscanner-ast >= 1.1.5, - dhscanner-bitcode >= 1.0.16 + dhscanner-bitcode >= 1.0.17 hs-source-dirs: src
src/Kbgen.hs view
@@ -70,6 +70,10 @@ ArgiForCall(..), DataflowEdge(..), ConstBoolTrue(..), + ConstNull(..), + GatedReturn(..), + Cond(..), + ReturnedValue(..), ClassAnnotation, CallableAnnotation, ParamiOfCallable(..), @@ -873,7 +877,7 @@ -- __When should I use this fact__ -- -- Any time a query needs to discriminate on the /value/ of a constant --- integer literal appearing in source code -- typically as an argument +-- integer literal appearing in source code, typically as an argument -- to a function that carries semantic information in that integer. -- The canonical example is the HTTP status code passed to a response -- constructor: @@ -918,6 +922,78 @@ -- This is how the fact will look inside the Prolog file -- -- @ +-- kb_const_null( Loc ). +-- @ +-- +-- __When should I use this fact__ +-- +-- Returning early from a function with a null value has many uses cases related to security. +-- ( Python @None@ and Ruby @nil@ use this predicate as well ) +-- +-- __Writing a predicate with this fact and others__ +-- +-- @ +-- kb_gated_return_null( Cond ) :- +-- kb_gated_return( Cond, ReturnedValue ), +-- kb_const_null( ReturnedValue ). +-- @ +-- +-- Other facts combined in this example predicate: +-- +-- * 'GatedReturn' +-- +data ConstNull = ConstNull Location deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) + +-- | +-- +-- __Name__ +-- +-- This is how the fact will look inside the Prolog file +-- +-- @ +-- kb_gated_return( Cond, ReturnedValue ). +-- @ +-- +-- __When should I use this fact__ +-- +-- Authenticating functions reject invalid credentials with an early return +-- from a guarded @if@. This fact pinpoints that rejection gate. +-- +-- __Writing a predicate with this fact and others__ +-- +-- @ +-- utils_early_return_null_on_missing_request_header_value( Callable, KeyName ) :- +-- kb_called_from( Call, Callable ), +-- kb_call_resolved( Call, \'nodejs.Request.headers.get\' ), +-- kb_arg_i_for_call( KeyArg, 0, Call ), +-- kb_const_string( KeyArg, KeyName ), +-- utils_intra_dataflow_path( Call, Var, _ ), +-- kb_gated_return_null( Cond ), +-- utils_intra_dataflow_path( Var, Cond, _ ). +-- +-- kb_gated_return_null( Cond ) :- kb_gated_return( Cond, RV ), kb_const_null( RV ). +-- @ +-- +-- Other facts combined in this example predicate: +-- +-- * 'ConstNull' +-- * 'CallResolved' +-- * 'ArgiForCall' +-- * 'ConstString' +-- * 'CalledFrom' +-- +data GatedReturn = GatedReturn + Cond -- ^ + ReturnedValue -- ^ + deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) + +-- | +-- +-- __Name__ +-- +-- This is how the fact will look inside the Prolog file +-- +-- @ -- kb_dataflow_edge( From, To ). -- @ -- @@ -941,6 +1017,8 @@ data Annotation = Annotation Location deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) data AssignedValue = AssignedValue Location deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) data ConstBoolTrue = ConstBoolTrue Location deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) +data Cond = Cond Location deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) +data ReturnedValue = ReturnedValue Location deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) data Keyword = Keyword String deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) data Resolved = Resolved Fqn.Fqn deriving ( Show, Eq, Ord, Generic, ToJSON, FromJSON ) @@ -979,6 +1057,8 @@ | CallResolvedCtor CallResolved | CalledFromCtor CalledFrom | ConstBoolTrueCtor ConstBoolTrue + | ConstNullCtor ConstNull + | GatedReturnCtor GatedReturn | MethodOfClassCtor MethodOfClass | ClassAnnotationCtor ClassAnnotation | ParamiOfCallableCtor ParamiOfCallable @@ -1014,6 +1094,8 @@ prologify (CallResolvedCtor content) = prologify_CallResolved content prologify (CalledFromCtor content) = prologify_CalledFrom content prologify (ConstBoolTrueCtor content) = prologify_ConstBoolTrue content +prologify (ConstNullCtor content) = prologify_ConstNull content +prologify (GatedReturnCtor content) = prologify_GatedReturn content prologify (MethodOfClassCtor content) = prologify_MethodOfClass content prologify (ClassAnnotationCtor content) = prologify_ClassAnnotation content prologify (ParamiOfCallableCtor content) = prologify_ParamiOfCallable content @@ -1094,6 +1176,18 @@ prologify_ConstBoolTrue :: ConstBoolTrue -> String prologify_ConstBoolTrue (ConstBoolTrue trueValue) = prologify_ConstBoolTrue' trueValue + +prologify_ConstNull' :: Location -> String +prologify_ConstNull' l = printf "kb_const_null( %s )." (locationify l) + +prologify_ConstNull :: ConstNull -> String +prologify_ConstNull (ConstNull loc) = prologify_ConstNull' loc + +prologify_GatedReturn' :: Location -> Location -> String +prologify_GatedReturn' c v = printf "kb_gated_return( %s, %s )." (locationify c) (locationify v) + +prologify_GatedReturn :: GatedReturn -> String +prologify_GatedReturn (GatedReturn (Cond c) (ReturnedValue v)) = prologify_GatedReturn' c v prologify_MethodOfClass' :: Location -> Location -> String prologify_MethodOfClass' m c = printf "kb_method_of_class( %s, %s )." (locationify m) (locationify c)
test/SmokeTests.hs view
@@ -1,6 +1,16 @@ module SmokeTests (runSmokeTests) where -import Kbgen (restoreloc) +import Kbgen + ( Cond (..) + , ConstNull (..) + , Fact (..) + , GatedReturn (..) + , ReturnedValue (..) + , locationify + , prologify + , restoreloc + ) +import Location (Location (..)) import Test.Hspec (Spec, hspec, it, shouldBe) it' :: IO () -> String -> Spec @@ -36,6 +46,30 @@ testLocationStringWithoutProperFormatExample3 :: IO () testLocationStringWithoutProperFormatExample3 = restoreloc locationStringWithoutProperFormatExample3 `shouldBe` Nothing +sampleLoc :: Word -> Location +sampleLoc n = + Location + { lineStart = n + , colStart = n + , lineEnd = n + , colEnd = n + , filename = "foo.c" + } + +testPrologifyConstNull :: IO () +testPrologifyConstNull = + let loc = sampleLoc 1 + expected = "kb_const_null( " ++ locationify loc ++ " )." + in prologify (ConstNullCtor (ConstNull loc)) `shouldBe` expected + +testPrologifyGatedReturn :: IO () +testPrologifyGatedReturn = + let condLoc = sampleLoc 1 + retLoc = sampleLoc 2 + gr = GatedReturn (Cond condLoc) (ReturnedValue retLoc) + expected = "kb_gated_return( " ++ locationify condLoc ++ ", " ++ locationify retLoc ++ " )." + in prologify (GatedReturnCtor gr) `shouldBe` expected + tests :: Spec tests = do it' testCompletelyInvalidLocationString "completelyInvalidLocationString should return Nothing" @@ -43,6 +77,8 @@ it' testLocationStringWithoutProperFormatExample1 "locationStringWithoutProperFormatExample1 should return Nothing" it' testLocationStringWithoutProperFormatExample2 "locationStringWithoutProperFormatExample2 should return Nothing" it' testLocationStringWithoutProperFormatExample3 "locationStringWithoutProperFormatExample3 should return Nothing" + it' testPrologifyConstNull "prologify_ConstNull should render kb_const_null( <loc> )." + it' testPrologifyGatedReturn "prologify_GatedReturn should render kb_gated_return( <cond>, <ret> )." runSmokeTests :: IO () runSmokeTests = hspec tests