@@ -3,10 +3,12 @@ private import cil
33private import dotnet
44private import DataFlowPublic
55private import DataFlowDispatch
6+ private import DataFlowImplCommon:: Public
67private import ControlFlowReachability
78private import DelegateDataFlow
89private import semmle.code.csharp.Caching
910private import semmle.code.csharp.ExprOrStmtParent
11+ private import semmle.code.csharp.controlflow.Guards
1012private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
1113private import semmle.code.csharp.dispatch.Dispatch
1214private import semmle.code.csharp.frameworks.EntityFramework
@@ -439,6 +441,22 @@ private module Cached {
439441 c .( FieldLikeContent ) .getField ( ) = node2 .asExpr ( ) .( FieldLikeRead ) .getTarget ( )
440442 )
441443 }
444+
445+ /**
446+ * Holds if the node `n` is unreachable when the call context is `call`.
447+ */
448+ cached
449+ predicate isUnreachableInCall ( Node n , DataFlowCall call ) {
450+ exists (
451+ SsaDefinitionNode paramNode , Ssa:: ExplicitDefinition param , Guard guard ,
452+ ControlFlow:: SuccessorTypes:: BooleanSuccessor bs
453+ |
454+ viableConstantBooleanParamArg ( paramNode , bs .getValue ( ) .booleanNot ( ) , call ) and
455+ paramNode .getDefinition ( ) = param and
456+ param .getARead ( ) = guard and
457+ guard .controlsBlock ( n .getControlFlowNode ( ) .getBasicBlock ( ) , bs )
458+ )
459+ }
442460}
443461
444462import Cached
@@ -1358,4 +1376,31 @@ class DataFlowType = DotNet::Type;
13581376
13591377class DataFlowLocation = Location ;
13601378
1361- predicate isUnreachableInCall ( Node n , DataFlowCall call ) { none ( ) } // stub implementation
1379+ /** Holds if `e` is an expression that always has the same Boolean value `val`. */
1380+ private predicate constantBooleanExpr ( Expr e , boolean val ) {
1381+ e = any ( AbstractValues:: BooleanValue bv | val = bv .getValue ( ) ) .getAnExpr ( )
1382+ or
1383+ exists ( Ssa:: ExplicitDefinition def , Expr src |
1384+ e = def .getARead ( ) and
1385+ src = def .getADefinition ( ) .getSource ( ) and
1386+ constantBooleanExpr ( src , val )
1387+ )
1388+ }
1389+
1390+ /** An argument that always has the same Boolean value. */
1391+ private class ConstantBooleanArgumentNode extends ExprNode {
1392+ ConstantBooleanArgumentNode ( ) { constantBooleanExpr ( this .( ArgumentNode ) .asExpr ( ) , _) }
1393+
1394+ /** Gets the Boolean value of this expression. */
1395+ boolean getBooleanValue ( ) { constantBooleanExpr ( this .getExpr ( ) , result ) }
1396+ }
1397+
1398+ pragma [ noinline]
1399+ private predicate viableConstantBooleanParamArg (
1400+ SsaDefinitionNode paramNode , boolean b , DataFlowCall call
1401+ ) {
1402+ exists ( ConstantBooleanArgumentNode arg |
1403+ viableParamArg ( call , paramNode , arg ) and
1404+ b = arg .getBooleanValue ( )
1405+ )
1406+ }
0 commit comments