9595
9696import cpp
9797private import new.DataFlow
98+ private import semmle.code.cpp.controlflow.IRGuards
9899private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as Private
99100private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
100101private import internal.FlowSummaryImpl
@@ -367,6 +368,8 @@ private predicate elementSpec(
367368) {
368369 sourceModel ( namespace , type , subtypes , name , signature , ext , _, _, _, _) or
369370 sinkModel ( namespace , type , subtypes , name , signature , ext , _, _, _, _) or
371+ barrierModel ( namespace , type , subtypes , name , signature , ext , _, _, _, _) or
372+ barrierGuardModel ( namespace , type , subtypes , name , signature , ext , _, _, _, _, _) or
370373 summaryModel ( namespace , type , subtypes , name , signature , ext , _, _, _, _, _)
371374}
372375
@@ -1028,6 +1031,84 @@ private module Cached {
10281031 isSinkNode ( n , kind , model ) and n .asNode ( ) = node
10291032 )
10301033 }
1034+
1035+ private newtype TKindModelPair =
1036+ TMkPair ( string kind , string model ) { isBarrierGuardNode ( _, _, kind , model ) }
1037+
1038+ private GuardValue convertAcceptingValue ( Public:: AcceptingValue av ) {
1039+ av .isTrue ( ) and result .asBooleanValue ( ) = true
1040+ or
1041+ av .isFalse ( ) and result .asBooleanValue ( ) = false
1042+ or
1043+ // NOTE: The below cases don't contribute anything currently since the
1044+ // callers immediately use `.asBooleanValue()` to convert the `GuardValue`
1045+ // to a boolean. Once we're willing to accept the breaking change of
1046+ // converting the barrier guard API to use `GuardValue`s instead `Boolean`s
1047+ // we can remove this restriction.
1048+ av .isNoException ( ) and result .getDualValue ( ) .isThrowsException ( )
1049+ or
1050+ av .isZero ( ) and result .asIntValue ( ) = 0
1051+ or
1052+ av .isNotZero ( ) and result .getDualValue ( ) .asIntValue ( ) = 0
1053+ or
1054+ av .isNull ( ) and result .isNullValue ( )
1055+ or
1056+ av .isNotNull ( ) and result .isNonNullValue ( )
1057+ }
1058+
1059+ private predicate barrierGuardChecks ( IRGuardCondition g , Expr e , boolean gv , TKindModelPair kmp ) {
1060+ exists (
1061+ SourceSinkInterpretationInput:: InterpretNode n , Public:: AcceptingValue acceptingvalue ,
1062+ string kind , string model
1063+ |
1064+ isBarrierGuardNode ( n , acceptingvalue , kind , model ) and
1065+ n .asNode ( ) .asExpr ( ) = e and
1066+ kmp = TMkPair ( kind , model ) and
1067+ gv = convertAcceptingValue ( acceptingvalue ) .asBooleanValue ( ) and
1068+ n .asNode ( ) .( Private:: ArgumentNode ) .getCall ( ) .asCallInstruction ( ) = g
1069+ )
1070+ }
1071+
1072+ private newtype TKindModelPairIntPair =
1073+ MkKindModelPairIntPair ( TKindModelPair pair , int indirectionIndex ) {
1074+ indirectionIndex > 0 and
1075+ Private:: nodeHasInstruction ( _, _, indirectionIndex ) and
1076+ exists ( pair )
1077+ }
1078+
1079+ private predicate indirectBarrierGuardChecks (
1080+ IRGuardCondition g , Expr e , boolean gv , TKindModelPairIntPair kmp
1081+ ) {
1082+ exists (
1083+ SourceSinkInterpretationInput:: InterpretNode interpretNode ,
1084+ Public:: AcceptingValue acceptingvalue , string kind , string model , int indirectionIndex ,
1085+ Private:: ArgumentNode arg
1086+ |
1087+ isBarrierGuardNode ( interpretNode , acceptingvalue , kind , model ) and
1088+ arg = interpretNode .asNode ( ) and
1089+ arg .asIndirectExpr ( indirectionIndex ) = e and
1090+ kmp = MkKindModelPairIntPair ( TMkPair ( kind , model ) , indirectionIndex ) and
1091+ gv = convertAcceptingValue ( acceptingvalue ) .asBooleanValue ( ) and
1092+ arg .getCall ( ) .asCallInstruction ( ) = g
1093+ )
1094+ }
1095+
1096+ /**
1097+ * Holds if `node` is specified as a barrier with the given kind in a MaD flow
1098+ * model.
1099+ */
1100+ cached
1101+ predicate barrierNode ( DataFlow:: Node node , string kind , string model ) {
1102+ exists ( SourceSinkInterpretationInput:: InterpretNode n |
1103+ isBarrierNode ( n , kind , model ) and n .asNode ( ) = node
1104+ )
1105+ or
1106+ DataFlow:: ParameterizedBarrierGuard< TKindModelPair , barrierGuardChecks / 4 > :: getABarrierNode ( TMkPair ( kind ,
1107+ model ) ) = node
1108+ or
1109+ DataFlow:: ParameterizedBarrierGuard< TKindModelPairIntPair , indirectBarrierGuardChecks / 4 > :: getAnIndirectBarrierNode ( MkKindModelPairIntPair ( TMkPair ( kind ,
1110+ model ) , _) ) = node
1111+ }
10311112}
10321113
10331114import Cached
@@ -1044,6 +1125,12 @@ predicate sourceNode(DataFlow::Node node, string kind) { sourceNode(node, kind,
10441125 */
10451126predicate sinkNode ( DataFlow:: Node node , string kind ) { sinkNode ( node , kind , _) }
10461127
1128+ /**
1129+ * Holds if `node` is specified as a barrier with the given kind in a MaD flow
1130+ * model.
1131+ */
1132+ predicate barrierNode ( DataFlow:: Node node , string kind ) { barrierNode ( node , kind , _) }
1133+
10471134private predicate interpretSummary (
10481135 Function f , string input , string output , string kind , string provenance , string model
10491136) {
0 commit comments