@@ -46,21 +46,23 @@ predicate predictableOnlyFlow(string name) {
4646
4747private DataFlow:: Node getNodeForSource ( Expr source ) {
4848 isUserInput ( source , _) and
49- (
50- result = DataFlow:: exprNode ( source )
51- or
52- // Some of the sources in `isUserInput` are intended to match the value of
53- // an expression, while others (those modeled below) are intended to match
54- // the taint that propagates out of an argument, like the `char *` argument
55- // to `gets`. It's impossible here to tell which is which, but the "access
56- // to argv" source is definitely not intended to match an output argument,
57- // and it causes false positives if we let it.
58- //
59- // This case goes together with the similar (but not identical) rule in
60- // `nodeIsBarrierIn`.
61- result = DataFlow:: definitionByReferenceNodeFromArgument ( source ) and
62- not argv ( source .( VariableAccess ) .getTarget ( ) )
63- )
49+ result = getNodeForExpr ( source )
50+ }
51+
52+ private DataFlow:: Node getNodeForExpr ( Expr node ) {
53+ result = DataFlow:: exprNode ( node )
54+ or
55+ // Some of the sources in `isUserInput` are intended to match the value of
56+ // an expression, while others (those modeled below) are intended to match
57+ // the taint that propagates out of an argument, like the `char *` argument
58+ // to `gets`. It's impossible here to tell which is which, but the "access
59+ // to argv" source is definitely not intended to match an output argument,
60+ // and it causes false positives if we let it.
61+ //
62+ // This case goes together with the similar (but not identical) rule in
63+ // `nodeIsBarrierIn`.
64+ result = DataFlow:: definitionByReferenceNodeFromArgument ( node ) and
65+ not argv ( node .( VariableAccess ) .getTarget ( ) )
6466}
6567
6668private class DefaultTaintTrackingCfg extends DataFlow:: Configuration {
@@ -537,6 +539,9 @@ module TaintedWithPath {
537539 * a characteristic predicate.
538540 */
539541 class TaintTrackingConfiguration extends TSingleton {
542+ /** Override this to specify which elements are sources in this configuration. */
543+ predicate isSource ( Expr source ) { exists ( getNodeForSource ( source ) ) }
544+
540545 /** Override this to specify which elements are sinks in this configuration. */
541546 abstract predicate isSink ( Element e ) ;
542547
@@ -553,7 +558,11 @@ module TaintedWithPath {
553558 private class AdjustedConfiguration extends DataFlow3:: Configuration {
554559 AdjustedConfiguration ( ) { this = "AdjustedConfiguration" }
555560
556- override predicate isSource ( DataFlow:: Node source ) { source = getNodeForSource ( _) }
561+ override predicate isSource ( DataFlow:: Node source ) {
562+ exists ( TaintTrackingConfiguration cfg , Expr e |
563+ cfg .isSource ( e ) and source = getNodeForExpr ( e )
564+ )
565+ }
557566
558567 override predicate isSink ( DataFlow:: Node sink ) {
559568 exists ( TaintTrackingConfiguration cfg | cfg .isSink ( adjustedSink ( sink ) ) )
@@ -596,7 +605,8 @@ module TaintedWithPath {
596605 exists ( AdjustedConfiguration cfg , DataFlow3:: Node sourceNode , DataFlow3:: Node sinkNode |
597606 cfg .hasFlow ( sourceNode , sinkNode )
598607 |
599- sourceNode = getNodeForSource ( e )
608+ sourceNode = getNodeForExpr ( e ) and
609+ exists ( TaintTrackingConfiguration ttCfg | ttCfg .isSource ( e ) )
600610 or
601611 e = adjustedSink ( sinkNode ) and
602612 exists ( TaintTrackingConfiguration ttCfg | ttCfg .isSink ( e ) )
@@ -650,7 +660,7 @@ module TaintedWithPath {
650660
651661 /** A PathNode whose `Element` is a source. It may also be a sink. */
652662 private class InitialPathNode extends EndpointPathNode {
653- InitialPathNode ( ) { exists ( getNodeForSource ( this .inner ( ) ) ) }
663+ InitialPathNode ( ) { exists ( TaintTrackingConfiguration cfg | cfg . isSource ( this .inner ( ) ) ) }
654664 }
655665
656666 /** A PathNode whose `Element` is a sink. It may also be a source. */
@@ -672,14 +682,14 @@ module TaintedWithPath {
672682 // Same for the first node
673683 exists ( WrapPathNode sourceNode |
674684 DataFlow3:: PathGraph:: edges ( sourceNode .inner ( ) , b .( WrapPathNode ) .inner ( ) ) and
675- sourceNode .inner ( ) .getNode ( ) = getNodeForSource ( a .( InitialPathNode ) .inner ( ) )
685+ sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( a .( InitialPathNode ) .inner ( ) )
676686 )
677687 or
678688 // Finally, handle the case where the path goes directly from a source to a
679689 // sink, meaning that they both need to be translated.
680690 exists ( WrapPathNode sinkNode , WrapPathNode sourceNode |
681691 DataFlow3:: PathGraph:: edges ( sourceNode .inner ( ) , sinkNode .inner ( ) ) and
682- sourceNode .inner ( ) .getNode ( ) = getNodeForSource ( a .( InitialPathNode ) .inner ( ) ) and
692+ sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( a .( InitialPathNode ) .inner ( ) ) and
683693 b .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
684694 )
685695 }
@@ -702,7 +712,7 @@ module TaintedWithPath {
702712 predicate taintedWithPath ( Expr source , Element tainted , PathNode sourceNode , PathNode sinkNode ) {
703713 exists ( AdjustedConfiguration cfg , DataFlow3:: Node flowSource , DataFlow3:: Node flowSink |
704714 source = sourceNode .( InitialPathNode ) .inner ( ) and
705- flowSource = getNodeForSource ( source ) and
715+ flowSource = getNodeForExpr ( source ) and
706716 cfg .hasFlow ( flowSource , flowSink ) and
707717 tainted = adjustedSink ( flowSink ) and
708718 tainted = sinkNode .( FinalPathNode ) .inner ( )
@@ -724,8 +734,8 @@ module TaintedWithPath {
724734 * through a global variable.
725735 */
726736 predicate taintedWithoutGlobals ( Element tainted ) {
727- exists ( PathNode sourceNode , FinalPathNode sinkNode |
728- sourceNode .( WrapPathNode ) .inner ( ) .getNode ( ) = getNodeForSource ( _ ) and
737+ exists ( AdjustedConfiguration cfg , PathNode sourceNode , FinalPathNode sinkNode |
738+ cfg . isSource ( sourceNode .( WrapPathNode ) .inner ( ) .getNode ( ) ) and
729739 edgesWithoutGlobals + ( sourceNode , sinkNode ) and
730740 tainted = sinkNode .inner ( )
731741 )
0 commit comments