packages feed

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 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