@@ -47,14 +47,24 @@ predicate predictableOnlyFlow(string name) {
47
47
]
48
48
}
49
49
50
- private DataFlow:: Node getNodeForSource ( Expr source ) {
51
- isUserInput ( source , _) and
52
- result = getNodeForExpr ( source )
50
+ private DataFlow:: Node getNodeForSource ( Element source ) {
51
+ (
52
+ // It is user input
53
+ isUserInput ( source , _) and
54
+ // But `isUserInput` also marks all uses of `argv` as user input, and we don't want those.
55
+ not argv ( source .( VariableAccess ) .getTarget ( ) )
56
+ or
57
+ // Instead, we want the actual parameter as user input.
58
+ argv ( source )
59
+ ) and
60
+ result = getNodeForElement ( source )
53
61
}
54
62
55
- private DataFlow:: Node getNodeForExpr ( Expr node ) {
63
+ private DataFlow:: Node getNodeForElement ( Element node ) {
56
64
result = DataFlow:: exprNode ( node )
57
65
or
66
+ result .asParameter ( ) = node
67
+ or
58
68
// Some of the sources in `isUserInput` are intended to match the value of
59
69
// an expression, while others (those modeled below) are intended to match
60
70
// the taint that propagates out of an argument, like the `char *` argument
@@ -194,13 +204,7 @@ private module Cached {
194
204
cached
195
205
predicate nodeIsBarrierIn ( DataFlow:: Node node ) {
196
206
// don't use dataflow into taint sources, as this leads to duplicate results.
197
- exists ( Expr source | isUserInput ( source , _) |
198
- node = DataFlow:: exprNode ( source )
199
- or
200
- // This case goes together with the similar (but not identical) rule in
201
- // `getNodeForSource`.
202
- node = DataFlow:: definitionByReferenceNodeFromArgument ( source )
203
- )
207
+ node = getNodeForSource ( _)
204
208
or
205
209
// don't use dataflow into binary instructions if both operands are unpredictable
206
210
exists ( BinaryInstruction iTo |
@@ -303,7 +307,7 @@ private import Cached
303
307
* If you need that you must call `taintedIncludingGlobalVars`.
304
308
*/
305
309
cached
306
- predicate tainted ( Expr source , Element tainted ) {
310
+ predicate tainted ( Element source , Element tainted ) {
307
311
exists ( DefaultTaintTrackingCfg cfg , DataFlow:: Node sink |
308
312
cfg .hasFlow ( getNodeForSource ( source ) , sink ) and
309
313
tainted = adjustedSink ( sink )
@@ -326,7 +330,7 @@ predicate tainted(Expr source, Element tainted) {
326
330
* through a global variable, then `globalVar = ""`.
327
331
*/
328
332
cached
329
- predicate taintedIncludingGlobalVars ( Expr source , Element tainted , string globalVar ) {
333
+ predicate taintedIncludingGlobalVars ( Element source , Element tainted , string globalVar ) {
330
334
tainted ( source , tainted ) and
331
335
globalVar = ""
332
336
or
@@ -376,13 +380,13 @@ module TaintedWithPath {
376
380
*/
377
381
class TaintTrackingConfiguration extends TSingleton {
378
382
/** Override this to specify which elements are sources in this configuration. */
379
- predicate isSource ( Expr source ) { exists ( getNodeForSource ( source ) ) }
383
+ predicate isSource ( Element source ) { exists ( getNodeForSource ( source ) ) }
380
384
381
385
/** Override this to specify which elements are sinks in this configuration. */
382
386
abstract predicate isSink ( Element e ) ;
383
387
384
388
/** Override this to specify which expressions are barriers in this configuration. */
385
- predicate isBarrier ( Expr e ) { nodeIsBarrier ( getNodeForExpr ( e ) ) }
389
+ predicate isBarrier ( Expr e ) { nodeIsBarrier ( getNodeForElement ( e ) ) }
386
390
387
391
/**
388
392
* Override this predicate to `any()` to allow taint to flow through global
@@ -398,8 +402,8 @@ module TaintedWithPath {
398
402
AdjustedConfiguration ( ) { this = "AdjustedConfiguration" }
399
403
400
404
override predicate isSource ( DataFlow:: Node source ) {
401
- exists ( TaintTrackingConfiguration cfg , Expr e |
402
- cfg .isSource ( e ) and source = getNodeForExpr ( e )
405
+ exists ( TaintTrackingConfiguration cfg , Element e |
406
+ cfg .isSource ( e ) and source = getNodeForElement ( e )
403
407
)
404
408
}
405
409
@@ -419,7 +423,9 @@ module TaintedWithPath {
419
423
}
420
424
421
425
override predicate isSanitizer ( DataFlow:: Node node ) {
422
- exists ( TaintTrackingConfiguration cfg , Expr e | cfg .isBarrier ( e ) and node = getNodeForExpr ( e ) )
426
+ exists ( TaintTrackingConfiguration cfg , Element e |
427
+ cfg .isBarrier ( e ) and node = getNodeForElement ( e )
428
+ )
423
429
}
424
430
425
431
override predicate isSanitizerIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
@@ -447,7 +453,7 @@ module TaintedWithPath {
447
453
exists ( AdjustedConfiguration cfg , DataFlow3:: Node sourceNode , DataFlow3:: Node sinkNode |
448
454
cfg .hasFlow ( sourceNode , sinkNode )
449
455
|
450
- sourceNode = getNodeForExpr ( e ) and
456
+ sourceNode = getNodeForElement ( e ) and
451
457
exists ( TaintTrackingConfiguration ttCfg | ttCfg .isSource ( e ) )
452
458
or
453
459
e = adjustedSink ( sinkNode ) and
@@ -506,7 +512,7 @@ module TaintedWithPath {
506
512
}
507
513
508
514
private class EndpointPathNode extends PathNode , TEndpointPathNode {
509
- Expr inner ( ) { this = TEndpointPathNode ( result ) }
515
+ Element inner ( ) { this = TEndpointPathNode ( result ) }
510
516
511
517
override string toString ( ) { result = this .inner ( ) .toString ( ) }
512
518
@@ -543,14 +549,14 @@ module TaintedWithPath {
543
549
// Same for the first node
544
550
exists ( WrapPathNode sourceNode |
545
551
DataFlow3:: PathGraph:: edges ( sourceNode .inner ( ) , b .( WrapPathNode ) .inner ( ) ) and
546
- sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( a .( InitialPathNode ) .inner ( ) )
552
+ sourceNode .inner ( ) .getNode ( ) = getNodeForElement ( a .( InitialPathNode ) .inner ( ) )
547
553
)
548
554
or
549
555
// Finally, handle the case where the path goes directly from a source to a
550
556
// sink, meaning that they both need to be translated.
551
557
exists ( WrapPathNode sinkNode , WrapPathNode sourceNode |
552
558
DataFlow3:: PathGraph:: edges ( sourceNode .inner ( ) , sinkNode .inner ( ) ) and
553
- sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( a .( InitialPathNode ) .inner ( ) ) and
559
+ sourceNode .inner ( ) .getNode ( ) = getNodeForElement ( a .( InitialPathNode ) .inner ( ) ) and
554
560
b .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
555
561
)
556
562
}
@@ -575,15 +581,15 @@ module TaintedWithPath {
575
581
exists ( WrapPathNode sourceNode |
576
582
DataFlow3:: PathGraph:: subpaths ( sourceNode .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
577
583
ret .( WrapPathNode ) .inner ( ) , out .( WrapPathNode ) .inner ( ) ) and
578
- sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( arg .( InitialPathNode ) .inner ( ) )
584
+ sourceNode .inner ( ) .getNode ( ) = getNodeForElement ( arg .( InitialPathNode ) .inner ( ) )
579
585
)
580
586
or
581
587
// Finally, handle the case where the path goes directly from a source to a
582
588
// sink, meaning that they both need to be translated.
583
589
exists ( WrapPathNode sinkNode , WrapPathNode sourceNode |
584
590
DataFlow3:: PathGraph:: subpaths ( sourceNode .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
585
591
ret .( WrapPathNode ) .inner ( ) , sinkNode .inner ( ) ) and
586
- sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( arg .( InitialPathNode ) .inner ( ) ) and
592
+ sourceNode .inner ( ) .getNode ( ) = getNodeForElement ( arg .( InitialPathNode ) .inner ( ) ) and
587
593
out .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
588
594
)
589
595
}
@@ -603,10 +609,10 @@ module TaintedWithPath {
603
609
* user input in a way that users can probably control the exact output of
604
610
* the computation.
605
611
*/
606
- predicate taintedWithPath ( Expr source , Element tainted , PathNode sourceNode , PathNode sinkNode ) {
612
+ predicate taintedWithPath ( Element source , Element tainted , PathNode sourceNode , PathNode sinkNode ) {
607
613
exists ( AdjustedConfiguration cfg , DataFlow3:: Node flowSource , DataFlow3:: Node flowSink |
608
614
source = sourceNode .( InitialPathNode ) .inner ( ) and
609
- flowSource = getNodeForExpr ( source ) and
615
+ flowSource = getNodeForElement ( source ) and
610
616
cfg .hasFlow ( flowSource , flowSink ) and
611
617
tainted = adjustedSink ( flowSink ) and
612
618
tainted = sinkNode .( FinalPathNode ) .inner ( )
0 commit comments