@@ -516,7 +516,7 @@ private module ThisFlow {
516516 */
517517cached
518518predicate localFlowStep ( Node nodeFrom , Node nodeTo ) {
519- simpleLocalFlowStep ( nodeFrom , nodeTo )
519+ simpleLocalFlowStep ( nodeFrom , nodeTo , _ )
520520 or
521521 // Field flow is not strictly a "step" but covers the whole function
522522 // transitively. There's no way to get a step-like relation out of the global
@@ -530,64 +530,67 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) {
530530 * This is the local flow predicate that's used as a building block in global
531531 * data flow. It may have less flow than the `localFlowStep` predicate.
532532 */
533- predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
534- // Expr -> Expr
535- exprToExprStep_nocfg ( nodeFrom .asExpr ( ) , nodeTo .asExpr ( ) )
536- or
537- // Assignment -> LValue post-update node
538- //
539- // This is used for assignments whose left-hand side is not a variable
540- // assignment or a storeStep but is still modeled by other means. It could be
541- // a call to `operator*` or `operator[]` where taint should flow to the
542- // post-update node of the qualifier.
543- exists ( AssignExpr assign |
544- nodeFrom .asExpr ( ) = assign and
545- nodeTo .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) = assign .getLValue ( )
546- )
547- or
548- // Node -> FlowVar -> VariableAccess
549- exists ( FlowVar var |
550- (
551- exprToVarStep ( nodeFrom .asExpr ( ) , var )
552- or
553- varSourceBaseCase ( var , nodeFrom .asParameter ( ) )
554- or
555- varSourceBaseCase ( var , nodeFrom .asUninitialized ( ) )
556- or
557- var .definedPartiallyAt ( nodeFrom .asPartialDefinition ( ) )
558- ) and
559- varToNodeStep ( var , nodeTo )
560- )
561- or
562- // Expr -> DefinitionByReferenceNode
563- exprToDefinitionByReferenceStep ( nodeFrom .asExpr ( ) , nodeTo .asDefiningArgument ( ) )
564- or
565- // `this` -> adjacent-`this`
566- ThisFlow:: adjacentThisRefs ( nodeFrom , nodeTo )
567- or
568- // post-update-`this` -> following-`this`-ref
569- ThisFlow:: adjacentThisRefs ( nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) , nodeTo )
570- or
571- // In `f(&x->a)`, this step provides the flow from post-`&` to post-`x->a`,
572- // from which there is field flow to `x` via reverse read.
573- exists ( PartialDefinition def , Expr inner , Expr outer |
574- def .definesExpressions ( inner , outer ) and
575- inner = nodeTo .( InnerPartialDefinitionNode ) .getPreUpdateNode ( ) .asExpr ( ) and
576- outer = nodeFrom .( PartialDefinitionNode ) .getPreUpdateNode ( ) .asExpr ( )
577- )
578- or
579- // Reverse flow: data that flows from the post-update node of a reference
580- // returned by a function call, back into the qualifier of that function.
581- // This allows data to flow 'in' through references returned by a modeled
582- // function such as `operator[]`.
583- exists ( DataFlowFunction f , Call call , FunctionInput inModel , FunctionOutput outModel |
584- call .getTarget ( ) = f and
585- inModel .isReturnValueDeref ( ) and
586- outModel .isQualifierObject ( ) and
587- f .hasDataFlow ( inModel , outModel ) and
588- nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) = call and
589- nodeTo .asDefiningArgument ( ) = call .getQualifier ( )
590- )
533+ predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo , string model ) {
534+ (
535+ // Expr -> Expr
536+ exprToExprStep_nocfg ( nodeFrom .asExpr ( ) , nodeTo .asExpr ( ) )
537+ or
538+ // Assignment -> LValue post-update node
539+ //
540+ // This is used for assignments whose left-hand side is not a variable
541+ // assignment or a storeStep but is still modeled by other means. It could be
542+ // a call to `operator*` or `operator[]` where taint should flow to the
543+ // post-update node of the qualifier.
544+ exists ( AssignExpr assign |
545+ nodeFrom .asExpr ( ) = assign and
546+ nodeTo .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) = assign .getLValue ( )
547+ )
548+ or
549+ // Node -> FlowVar -> VariableAccess
550+ exists ( FlowVar var |
551+ (
552+ exprToVarStep ( nodeFrom .asExpr ( ) , var )
553+ or
554+ varSourceBaseCase ( var , nodeFrom .asParameter ( ) )
555+ or
556+ varSourceBaseCase ( var , nodeFrom .asUninitialized ( ) )
557+ or
558+ var .definedPartiallyAt ( nodeFrom .asPartialDefinition ( ) )
559+ ) and
560+ varToNodeStep ( var , nodeTo )
561+ )
562+ or
563+ // Expr -> DefinitionByReferenceNode
564+ exprToDefinitionByReferenceStep ( nodeFrom .asExpr ( ) , nodeTo .asDefiningArgument ( ) )
565+ or
566+ // `this` -> adjacent-`this`
567+ ThisFlow:: adjacentThisRefs ( nodeFrom , nodeTo )
568+ or
569+ // post-update-`this` -> following-`this`-ref
570+ ThisFlow:: adjacentThisRefs ( nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) , nodeTo )
571+ or
572+ // In `f(&x->a)`, this step provides the flow from post-`&` to post-`x->a`,
573+ // from which there is field flow to `x` via reverse read.
574+ exists ( PartialDefinition def , Expr inner , Expr outer |
575+ def .definesExpressions ( inner , outer ) and
576+ inner = nodeTo .( InnerPartialDefinitionNode ) .getPreUpdateNode ( ) .asExpr ( ) and
577+ outer = nodeFrom .( PartialDefinitionNode ) .getPreUpdateNode ( ) .asExpr ( )
578+ )
579+ or
580+ // Reverse flow: data that flows from the post-update node of a reference
581+ // returned by a function call, back into the qualifier of that function.
582+ // This allows data to flow 'in' through references returned by a modeled
583+ // function such as `operator[]`.
584+ exists ( DataFlowFunction f , Call call , FunctionInput inModel , FunctionOutput outModel |
585+ call .getTarget ( ) = f and
586+ inModel .isReturnValueDeref ( ) and
587+ outModel .isQualifierObject ( ) and
588+ f .hasDataFlow ( inModel , outModel ) and
589+ nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) = call and
590+ nodeTo .asDefiningArgument ( ) = call .getQualifier ( )
591+ )
592+ ) and
593+ model = ""
591594}
592595
593596/**
0 commit comments