@@ -195,3 +195,62 @@ class ExternalFileObject extends TaintKind {
195195 name = "read" and result = this .getValue ( )
196196 }
197197}
198+
199+ /**
200+ * Temporary sanitizer for the tainted result from `urlsplit` and `urlparse`. Can be used to reduce FPs until
201+ * we have better support for namedtuples.
202+ *
203+ * Will clear **all** taint on a test of the kind. That is, on the true edge of any matching test,
204+ * all fields/indexes will be cleared of taint.
205+ *
206+ * Handles:
207+ * - `if splitres.netloc == "KNOWN_VALUE"`
208+ * - `if splitres[0] == "KNOWN_VALUE"`
209+ */
210+ class UrlsplitUrlparseTempSanitizer extends Sanitizer {
211+ // TODO: remove this once we have better support for named tuples
212+
213+ UrlsplitUrlparseTempSanitizer ( ) { this = "UrlsplitUrlparseTempSanitizer" }
214+
215+ override predicate sanitizingEdge ( TaintKind taint , PyEdgeRefinement test ) {
216+ (
217+ taint instanceof ExternalUrlSplitResult
218+ or
219+ taint instanceof ExternalUrlParseResult
220+ ) and
221+ exists ( ControlFlowNode foobar |
222+ foobar .( SubscriptNode ) .getObject ( ) = test .getInput ( ) .getAUse ( )
223+ or
224+ foobar .( AttrNode ) .getObject ( ) = test .getInput ( ) .getAUse ( )
225+ |
226+ clears_taint ( _, foobar , test .getTest ( ) , test .getSense ( ) )
227+ )
228+ }
229+
230+ private predicate clears_taint ( ControlFlowNode final_test , ControlFlowNode tainted , ControlFlowNode test , boolean sense ) {
231+ test_equality_with_const ( final_test , tainted , sense )
232+ or
233+ test .( UnaryExprNode ) .getNode ( ) .getOp ( ) instanceof Not and
234+ exists ( ControlFlowNode nested_test |
235+ nested_test = test .( UnaryExprNode ) .getOperand ( ) and
236+ clears_taint ( final_test , tainted , nested_test , sense .booleanNot ( ) )
237+ )
238+ }
239+
240+ /** holds for `== "KNOWN_VALUE"` on `true` edge, and `!= "KNOWN_VALUE"` on `false` edge */
241+ private predicate test_equality_with_const ( CompareNode cmp , ControlFlowNode operand , boolean sense ) {
242+ exists ( ControlFlowNode const , Cmpop op |
243+ const .getNode ( ) instanceof StrConst
244+ |
245+ (
246+ cmp .operands ( const , op , operand )
247+ or
248+ cmp .operands ( operand , op , const )
249+ ) and (
250+ op instanceof Eq and sense = true
251+ or
252+ op instanceof NotEq and sense = false
253+ )
254+ )
255+ }
256+ }
0 commit comments