@@ -81,22 +81,48 @@ abstract class SensitiveVariableAccess extends SensitiveExpr {
81
81
/** A write to a location that might contain sensitive data. */
82
82
abstract class SensitiveWrite extends DataFlow:: Node { }
83
83
84
+ /**
85
+ * Holds if `node` is a write to a variable or property named `name`.
86
+ *
87
+ * Helper predicate factored out for performance,
88
+ * to filter `name` as much as possible before using it in
89
+ * regex matching.
90
+ */
91
+ pragma [ nomagic]
92
+ private predicate writesProperty ( DataFlow:: Node node , string name ) {
93
+ exists ( DataFlow:: PropWrite pwn |
94
+ pwn .getPropertyName ( ) = name and
95
+ pwn .getRhs ( ) = node
96
+ )
97
+ or
98
+ exists ( VarDef v | v .getAVariable ( ) .getName ( ) = name |
99
+ if exists ( v .getSource ( ) )
100
+ then v .getSource ( ) = node .asExpr ( )
101
+ else node = DataFlow:: ssaDefinitionNode ( SSA:: definition ( v ) )
102
+ )
103
+ }
104
+
84
105
/** A write to a variable or property that might contain sensitive data. */
85
106
private class BasicSensitiveWrite extends SensitiveWrite {
86
107
SensitiveDataClassification classification ;
87
108
88
109
BasicSensitiveWrite ( ) {
89
- exists ( string name | nameIndicatesSensitiveData ( name , classification ) |
90
- exists ( DataFlow:: PropWrite pwn |
91
- pwn .getPropertyName ( ) = name and
92
- pwn .getRhs ( ) = this
93
- )
94
- or
95
- exists ( VarDef v | v .getAVariable ( ) .getName ( ) = name |
96
- if exists ( v .getSource ( ) )
97
- then v .getSource ( ) = this .asExpr ( )
98
- else this = DataFlow:: ssaDefinitionNode ( SSA:: definition ( v ) )
99
- )
110
+ exists ( string name |
111
+ /*
112
+ * PERFORMANCE OPTIMISATION:
113
+ * `nameIndicatesSensitiveData` performs a `regexpMatch` on `name`.
114
+ * To carry out a regex match, we must first compute the Cartesian product
115
+ * of all possible `name`s and regexes, then match.
116
+ * To keep this product as small as possible,
117
+ * we want to filter `name` as much as possible before the product.
118
+ *
119
+ * Do this by factoring out a helper predicate containing the filtering
120
+ * logic that restricts `name`. This helper predicate will get picked first
121
+ * in the join order, since it is the only call here that binds `name`.
122
+ */
123
+
124
+ writesProperty ( this , name ) and
125
+ nameIndicatesSensitiveData ( name , classification )
100
126
)
101
127
}
102
128
0 commit comments