@@ -3,6 +3,15 @@ private import DataFlowPublic
3
3
import semmle.python.SpecialMethods
4
4
private import semmle.python.essa.SsaCompute
5
5
private import semmle.python.dataflow.new.internal.ImportStar
6
+ // Since we allow extra data-flow steps from modeled frameworks, we import these
7
+ // up-front, to ensure these are included. This provides a more seamless experience from
8
+ // a user point of view, since they don't need to know they need to import a specific
9
+ // set of .qll files to get the same data-flow steps as they are used to seeing. This
10
+ // also ensures that we don't end up re-evaluating data-flow because it has different
11
+ // global steps in some configurations.
12
+ //
13
+ // This matches behavior in C#.
14
+ private import semmle.python.Frameworks
6
15
7
16
/** Gets the callable in which this node occurs. */
8
17
DataFlowCallable nodeGetEnclosingCallable ( Node n ) { result = n .getEnclosingCallable ( ) }
@@ -943,6 +952,24 @@ string ppReprType(DataFlowType t) { none() }
943
952
* taken into account.
944
953
*/
945
954
predicate jumpStep ( Node nodeFrom , Node nodeTo ) {
955
+ jumpStepSharedWithTypeTracker ( nodeFrom , nodeTo )
956
+ or
957
+ jumpStepNotSharedWithTypeTracker ( nodeFrom , nodeTo )
958
+ }
959
+
960
+ /**
961
+ * Set of jumpSteps that are shared with type-tracker implementation.
962
+ *
963
+ * For ORM modeling we want to add jumpsteps to global dataflow, but since these are
964
+ * based on type-trackers, it's important that these new ORM jumsteps are not used in
965
+ * the type-trackers as well, as that would make evaluation of type-tracking recursive
966
+ * with the new jumpsteps.
967
+ *
968
+ * Holds if `pred` can flow to `succ`, by jumping from one callable to
969
+ * another. Additional steps specified by the configuration are *not*
970
+ * taken into account.
971
+ */
972
+ predicate jumpStepSharedWithTypeTracker ( Node nodeFrom , Node nodeTo ) {
946
973
runtimeJumpStep ( nodeFrom , nodeTo )
947
974
or
948
975
// Read of module attribute:
@@ -956,6 +983,22 @@ predicate jumpStep(Node nodeFrom, Node nodeTo) {
956
983
defaultValueFlowStep ( nodeFrom , nodeTo )
957
984
}
958
985
986
+ /**
987
+ * Set of jumpSteps that are NOT shared with type-tracker implementation.
988
+ *
989
+ * For ORM modeling we want to add jumpsteps to global dataflow, but since these are
990
+ * based on type-trackers, it's important that these new ORM jumsteps are not used in
991
+ * the type-trackers as well, as that would make evaluation of type-tracking recursive
992
+ * with the new jumpsteps.
993
+ *
994
+ * Holds if `pred` can flow to `succ`, by jumping from one callable to
995
+ * another. Additional steps specified by the configuration are *not*
996
+ * taken into account.
997
+ */
998
+ predicate jumpStepNotSharedWithTypeTracker ( Node nodeFrom , Node nodeTo ) {
999
+ any ( Orm:: AdditionalOrmSteps es ) .jumpStep ( nodeFrom , nodeTo )
1000
+ }
1001
+
959
1002
/**
960
1003
* Holds if the module `m` defines a name `name` by assigning `defn` to it. This is an
961
1004
* overapproximation, as `name` may not in fact be exported (e.g. by defining an `__all__` that does
@@ -999,6 +1042,51 @@ predicate storeStep(Node nodeFrom, Content c, Node nodeTo) {
999
1042
kwOverflowStoreStep ( nodeFrom , c , nodeTo )
1000
1043
or
1001
1044
matchStoreStep ( nodeFrom , c , nodeTo )
1045
+ or
1046
+ any ( Orm:: AdditionalOrmSteps es ) .storeStep ( nodeFrom , c , nodeTo )
1047
+ }
1048
+
1049
+ /**
1050
+ * INTERNAL: Do not use.
1051
+ *
1052
+ * Provides classes for modeling data-flow through ORM models saved in a DB.
1053
+ */
1054
+ module Orm {
1055
+ /**
1056
+ * INTERNAL: Do not use.
1057
+ *
1058
+ * A unit class for adding additional data-flow steps for ORM models.
1059
+ */
1060
+ class AdditionalOrmSteps extends Unit {
1061
+ /**
1062
+ * Holds if data can flow from `nodeFrom` to `nodeTo` via an assignment to
1063
+ * content `c`.
1064
+ */
1065
+ abstract predicate storeStep ( Node nodeFrom , Content c , Node nodeTo ) ;
1066
+
1067
+ /**
1068
+ * Holds if `pred` can flow to `succ`, by jumping from one callable to
1069
+ * another. Additional steps specified by the configuration are *not*
1070
+ * taken into account.
1071
+ */
1072
+ abstract predicate jumpStep ( Node nodeFrom , Node nodeTo ) ;
1073
+ }
1074
+
1075
+ /** A synthetic node representing the data for an ORM model saved in a DB. */
1076
+ class SyntheticOrmModelNode extends Node , TSyntheticOrmModelNode {
1077
+ Class cls ;
1078
+
1079
+ SyntheticOrmModelNode ( ) { this = TSyntheticOrmModelNode ( cls ) }
1080
+
1081
+ override string toString ( ) { result = "[orm-model] " + cls .toString ( ) }
1082
+
1083
+ override Scope getScope ( ) { result = cls .getEnclosingScope ( ) }
1084
+
1085
+ override Location getLocation ( ) { result = cls .getLocation ( ) }
1086
+
1087
+ /** Gets the class that defines this ORM model. */
1088
+ Class getClass ( ) { result = cls }
1089
+ }
1002
1090
}
1003
1091
1004
1092
/** Data flows from an element of a list to the list. */
0 commit comments