diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index d65e33bffbb5..1f42c21d5a73 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -198,126 +198,130 @@ private module Cached { /** * The final flow-through calculation: * - * - Input access paths are abstracted with a `ContentOption` parameter - * that represents the head of the access path. `TContentNone()` means that - * the access path is unrestricted. + * - Calculated flow is either value-preserving (`read = TReadStepTypesNone()`) + * or summarized as a single read step with before and after types recorded + * in the `ReadStepTypesOption` parameter. * - Types are checked using the `compatibleTypes()` relation. */ private module Final { /** * Holds if `p` can flow to `node` in the same callable using only - * value-preserving steps, not taking call contexts into account. + * value-preserving steps and possibly a single read step, not taking + * call contexts into account. * - * `contentIn` describes the content of `p` that can flow to `node` - * (if any), `t2` is the type of the tracked value, and `t1` is the - * type before reading `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ - predicate parameterValueFlow( - ParameterNode p, Node node, ContentOption contentIn, DataFlowType t1, DataFlowType t2 - ) { - parameterValueFlow0(p, node, contentIn, t1, t2) and + predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) { + parameterValueFlow0(p, node, read) and if node instanceof CastingNode - then compatibleTypes(t2, getErasedNodeTypeBound(node)) + then + // normal flow through + read = TReadStepTypesNone() and + compatibleTypes(getErasedNodeTypeBound(p), getErasedNodeTypeBound(node)) + or + // getter + compatibleTypes(read.getContentType(), getErasedNodeTypeBound(node)) else any() } pragma[nomagic] - private predicate parameterValueFlow0( - ParameterNode p, Node node, ContentOption contentIn, DataFlowType t1, DataFlowType t2 - ) { + private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) { p = node and Cand::cand(p, _) and - contentIn = TContentNone() and - t1 = getErasedNodeTypeBound(p) and - t2 = t1 + read = TReadStepTypesNone() or // local flow exists(Node mid | - parameterValueFlow(p, mid, contentIn, t1, t2) and + parameterValueFlow(p, mid, read) and LocalFlowBigStep::localFlowBigStep(mid, node) ) or // read exists(Node mid | - parameterValueFlow(p, mid, TContentNone(), _, t1) and - readStep(mid, contentIn.getContent(), node) and + parameterValueFlow(p, mid, TReadStepTypesNone()) and + readStepWithTypes(mid, read.getContainerType(), read.getContent(), node, + read.getContentType()) and Cand::parameterValueFlowReturnCand(p, _, true) and - compatibleTypes(t1, getErasedNodeTypeBound(mid)) and - t2 = getErasedNodeTypeBound(node) + compatibleTypes(getErasedNodeTypeBound(p), read.getContainerType()) ) or // flow through: no prior read - exists(ArgumentNode arg, DataFlowType t0_, DataFlowType t1_, DataFlowType t2_ | - parameterValueFlowArg(p, arg, TContentNone(), _, t0_) and - argumentValueFlowsThrough(arg, contentIn, node, t1_, t2_) and - if contentIn = TContentNone() - then t1 = t0_ and t2 = t1 - else ( - t1 = t1_ and - t2 = t2_ - ) + exists(ArgumentNode arg | + parameterValueFlowArg(p, arg, TReadStepTypesNone()) and + argumentValueFlowsThrough(arg, read, node) ) or // flow through: no read inside method exists(ArgumentNode arg | - parameterValueFlowArg(p, arg, contentIn, t1, t2) and - argumentValueFlowsThrough(arg, TContentNone(), node, _, _) + parameterValueFlowArg(p, arg, read) and + argumentValueFlowsThrough(arg, TReadStepTypesNone(), node) ) } pragma[nomagic] private predicate parameterValueFlowArg( - ParameterNode p, ArgumentNode arg, ContentOption contentIn, DataFlowType t1, DataFlowType t2 + ParameterNode p, ArgumentNode arg, ReadStepTypesOption read ) { - parameterValueFlow(p, arg, contentIn, t1, t2) and + parameterValueFlow(p, arg, read) and Cand::argumentValueFlowsThroughCand(arg, _, _) } pragma[nomagic] private predicate argumentValueFlowsThrough0( - DataFlowCall call, ArgumentNode arg, ReturnKind kind, ContentOption contentIn, - DataFlowType t1, DataFlowType t2 + DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read ) { exists(ParameterNode param | viableParamArg(call, param, arg) | - parameterValueFlowReturn(param, kind, contentIn, t1, t2) + parameterValueFlowReturn(param, kind, read) ) } /** - * Holds if `arg` flows to `out` through a call using only value-preserving steps, - * not taking call contexts into account. + * Holds if `arg` flows to `out` through a call using only + * value-preserving steps and possibly a single read step, not taking + * call contexts into account. * - * `contentIn` describes the content of `arg` that can flow to `out` (if any), - * `t2` is the type of the tracked value, and `t1` is the type before reading - * `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ pragma[nomagic] - predicate argumentValueFlowsThrough( - ArgumentNode arg, ContentOption contentIn, Node out, DataFlowType t1, DataFlowType t2 - ) { + predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) { exists(DataFlowCall call, ReturnKind kind | - argumentValueFlowsThrough0(call, arg, kind, contentIn, t1, t2) and - out = getAnOutNode(call, kind) and - compatibleTypes(t2, getErasedNodeTypeBound(out)) and - if contentIn = TContentNone() - then compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out)) - else compatibleTypes(getErasedNodeTypeBound(arg), t1) + argumentValueFlowsThrough0(call, arg, kind, read) and + out = getAnOutNode(call, kind) + | + // normal flow through + read = TReadStepTypesNone() and + compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out)) + or + // getter + compatibleTypes(getErasedNodeTypeBound(arg), read.getContainerType()) and + compatibleTypes(read.getContentType(), getErasedNodeTypeBound(out)) ) } + /** + * Holds if `arg` flows to `out` through a call using only + * value-preserving steps and a single read step, not taking call + * contexts into account, thus representing a getter-step. + */ + predicate getterStep(ArgumentNode arg, Content c, Node out) { + argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out) + } + /** * Holds if `p` can flow to a return node of kind `kind` in the same - * callable using only value-preserving steps. + * callable using only value-preserving steps and possibly a single read + * step. * - * `contentIn` describes the content of `p` that can flow to the return - * node (if any), `t2` is the type of the tracked value, and `t1` is the - * type before reading `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ private predicate parameterValueFlowReturn( - ParameterNode p, ReturnKind kind, ContentOption contentIn, DataFlowType t1, DataFlowType t2 + ParameterNode p, ReturnKind kind, ReadStepTypesOption read ) { exists(ReturnNode ret | - parameterValueFlow(p, ret, contentIn, t1, t2) and + parameterValueFlow(p, ret, read) and kind = ret.getKind() ) } @@ -332,21 +336,25 @@ private module Cached { */ cached predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) { - parameterValueFlow(p, n.getPreUpdateNode(), TContentNone(), _, _) + parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone()) } - private predicate store(Node node1, Content c, Node node2, DataFlowType containerType) { + private predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { storeStep(node1, c, node2) and readStep(_, c, _) and + contentType = getErasedNodeTypeBound(node1) and containerType = getErasedNodeTypeBound(node2) or exists(Node n1, Node n2 | n1 = node1.(PostUpdateNode).getPreUpdateNode() and n2 = node2.(PostUpdateNode).getPreUpdateNode() | - argumentValueFlowsThrough(n2, TContentSome(c), n1, containerType, _) + argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1) or readStep(n2, c, n1) and + contentType = getErasedNodeTypeBound(n1) and containerType = getErasedNodeTypeBound(n2) ) } @@ -359,8 +367,8 @@ private module Cached { * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2) { - store(node1, tc.getContent(), node2, tc.getContainerType()) + predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { + store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) } import FlowThrough @@ -408,7 +416,7 @@ private module Cached { TBooleanSome(boolean b) { b = true or b = false } cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, t) } + newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } cached newtype TAccessPathFront = @@ -436,21 +444,30 @@ class CastingNode extends Node { } } -newtype TContentOption = - TContentNone() or - TContentSome(Content c) +private predicate readStepWithTypes( + Node n1, DataFlowType container, Content c, Node n2, DataFlowType content +) { + readStep(n1, c, n2) and + container = getErasedNodeTypeBound(n1) and + content = getErasedNodeTypeBound(n2) +} -private class ContentOption extends TContentOption { - Content getContent() { this = TContentSome(result) } +private newtype TReadStepTypesOption = + TReadStepTypesNone() or + TReadStepTypesSome(DataFlowType container, Content c, DataFlowType content) { + readStepWithTypes(_, container, c, _, content) + } - predicate hasContent() { exists(this.getContent()) } +private class ReadStepTypesOption extends TReadStepTypesOption { + predicate isSome() { this instanceof TReadStepTypesSome } - string toString() { - result = this.getContent().toString() - or - not this.hasContent() and - result = "" - } + DataFlowType getContainerType() { this = TReadStepTypesSome(result, _, _) } + + Content getContent() { this = TReadStepTypesSome(_, result, _) } + + DataFlowType getContentType() { this = TReadStepTypesSome(_, _, result) } + + string toString() { if this.isSome() then result = "Some(..)" else result = "None()" } } /** diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index d65e33bffbb5..1f42c21d5a73 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -198,126 +198,130 @@ private module Cached { /** * The final flow-through calculation: * - * - Input access paths are abstracted with a `ContentOption` parameter - * that represents the head of the access path. `TContentNone()` means that - * the access path is unrestricted. + * - Calculated flow is either value-preserving (`read = TReadStepTypesNone()`) + * or summarized as a single read step with before and after types recorded + * in the `ReadStepTypesOption` parameter. * - Types are checked using the `compatibleTypes()` relation. */ private module Final { /** * Holds if `p` can flow to `node` in the same callable using only - * value-preserving steps, not taking call contexts into account. + * value-preserving steps and possibly a single read step, not taking + * call contexts into account. * - * `contentIn` describes the content of `p` that can flow to `node` - * (if any), `t2` is the type of the tracked value, and `t1` is the - * type before reading `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ - predicate parameterValueFlow( - ParameterNode p, Node node, ContentOption contentIn, DataFlowType t1, DataFlowType t2 - ) { - parameterValueFlow0(p, node, contentIn, t1, t2) and + predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) { + parameterValueFlow0(p, node, read) and if node instanceof CastingNode - then compatibleTypes(t2, getErasedNodeTypeBound(node)) + then + // normal flow through + read = TReadStepTypesNone() and + compatibleTypes(getErasedNodeTypeBound(p), getErasedNodeTypeBound(node)) + or + // getter + compatibleTypes(read.getContentType(), getErasedNodeTypeBound(node)) else any() } pragma[nomagic] - private predicate parameterValueFlow0( - ParameterNode p, Node node, ContentOption contentIn, DataFlowType t1, DataFlowType t2 - ) { + private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) { p = node and Cand::cand(p, _) and - contentIn = TContentNone() and - t1 = getErasedNodeTypeBound(p) and - t2 = t1 + read = TReadStepTypesNone() or // local flow exists(Node mid | - parameterValueFlow(p, mid, contentIn, t1, t2) and + parameterValueFlow(p, mid, read) and LocalFlowBigStep::localFlowBigStep(mid, node) ) or // read exists(Node mid | - parameterValueFlow(p, mid, TContentNone(), _, t1) and - readStep(mid, contentIn.getContent(), node) and + parameterValueFlow(p, mid, TReadStepTypesNone()) and + readStepWithTypes(mid, read.getContainerType(), read.getContent(), node, + read.getContentType()) and Cand::parameterValueFlowReturnCand(p, _, true) and - compatibleTypes(t1, getErasedNodeTypeBound(mid)) and - t2 = getErasedNodeTypeBound(node) + compatibleTypes(getErasedNodeTypeBound(p), read.getContainerType()) ) or // flow through: no prior read - exists(ArgumentNode arg, DataFlowType t0_, DataFlowType t1_, DataFlowType t2_ | - parameterValueFlowArg(p, arg, TContentNone(), _, t0_) and - argumentValueFlowsThrough(arg, contentIn, node, t1_, t2_) and - if contentIn = TContentNone() - then t1 = t0_ and t2 = t1 - else ( - t1 = t1_ and - t2 = t2_ - ) + exists(ArgumentNode arg | + parameterValueFlowArg(p, arg, TReadStepTypesNone()) and + argumentValueFlowsThrough(arg, read, node) ) or // flow through: no read inside method exists(ArgumentNode arg | - parameterValueFlowArg(p, arg, contentIn, t1, t2) and - argumentValueFlowsThrough(arg, TContentNone(), node, _, _) + parameterValueFlowArg(p, arg, read) and + argumentValueFlowsThrough(arg, TReadStepTypesNone(), node) ) } pragma[nomagic] private predicate parameterValueFlowArg( - ParameterNode p, ArgumentNode arg, ContentOption contentIn, DataFlowType t1, DataFlowType t2 + ParameterNode p, ArgumentNode arg, ReadStepTypesOption read ) { - parameterValueFlow(p, arg, contentIn, t1, t2) and + parameterValueFlow(p, arg, read) and Cand::argumentValueFlowsThroughCand(arg, _, _) } pragma[nomagic] private predicate argumentValueFlowsThrough0( - DataFlowCall call, ArgumentNode arg, ReturnKind kind, ContentOption contentIn, - DataFlowType t1, DataFlowType t2 + DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read ) { exists(ParameterNode param | viableParamArg(call, param, arg) | - parameterValueFlowReturn(param, kind, contentIn, t1, t2) + parameterValueFlowReturn(param, kind, read) ) } /** - * Holds if `arg` flows to `out` through a call using only value-preserving steps, - * not taking call contexts into account. + * Holds if `arg` flows to `out` through a call using only + * value-preserving steps and possibly a single read step, not taking + * call contexts into account. * - * `contentIn` describes the content of `arg` that can flow to `out` (if any), - * `t2` is the type of the tracked value, and `t1` is the type before reading - * `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ pragma[nomagic] - predicate argumentValueFlowsThrough( - ArgumentNode arg, ContentOption contentIn, Node out, DataFlowType t1, DataFlowType t2 - ) { + predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) { exists(DataFlowCall call, ReturnKind kind | - argumentValueFlowsThrough0(call, arg, kind, contentIn, t1, t2) and - out = getAnOutNode(call, kind) and - compatibleTypes(t2, getErasedNodeTypeBound(out)) and - if contentIn = TContentNone() - then compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out)) - else compatibleTypes(getErasedNodeTypeBound(arg), t1) + argumentValueFlowsThrough0(call, arg, kind, read) and + out = getAnOutNode(call, kind) + | + // normal flow through + read = TReadStepTypesNone() and + compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out)) + or + // getter + compatibleTypes(getErasedNodeTypeBound(arg), read.getContainerType()) and + compatibleTypes(read.getContentType(), getErasedNodeTypeBound(out)) ) } + /** + * Holds if `arg` flows to `out` through a call using only + * value-preserving steps and a single read step, not taking call + * contexts into account, thus representing a getter-step. + */ + predicate getterStep(ArgumentNode arg, Content c, Node out) { + argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out) + } + /** * Holds if `p` can flow to a return node of kind `kind` in the same - * callable using only value-preserving steps. + * callable using only value-preserving steps and possibly a single read + * step. * - * `contentIn` describes the content of `p` that can flow to the return - * node (if any), `t2` is the type of the tracked value, and `t1` is the - * type before reading `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ private predicate parameterValueFlowReturn( - ParameterNode p, ReturnKind kind, ContentOption contentIn, DataFlowType t1, DataFlowType t2 + ParameterNode p, ReturnKind kind, ReadStepTypesOption read ) { exists(ReturnNode ret | - parameterValueFlow(p, ret, contentIn, t1, t2) and + parameterValueFlow(p, ret, read) and kind = ret.getKind() ) } @@ -332,21 +336,25 @@ private module Cached { */ cached predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) { - parameterValueFlow(p, n.getPreUpdateNode(), TContentNone(), _, _) + parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone()) } - private predicate store(Node node1, Content c, Node node2, DataFlowType containerType) { + private predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { storeStep(node1, c, node2) and readStep(_, c, _) and + contentType = getErasedNodeTypeBound(node1) and containerType = getErasedNodeTypeBound(node2) or exists(Node n1, Node n2 | n1 = node1.(PostUpdateNode).getPreUpdateNode() and n2 = node2.(PostUpdateNode).getPreUpdateNode() | - argumentValueFlowsThrough(n2, TContentSome(c), n1, containerType, _) + argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1) or readStep(n2, c, n1) and + contentType = getErasedNodeTypeBound(n1) and containerType = getErasedNodeTypeBound(n2) ) } @@ -359,8 +367,8 @@ private module Cached { * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2) { - store(node1, tc.getContent(), node2, tc.getContainerType()) + predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { + store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) } import FlowThrough @@ -408,7 +416,7 @@ private module Cached { TBooleanSome(boolean b) { b = true or b = false } cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, t) } + newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } cached newtype TAccessPathFront = @@ -436,21 +444,30 @@ class CastingNode extends Node { } } -newtype TContentOption = - TContentNone() or - TContentSome(Content c) +private predicate readStepWithTypes( + Node n1, DataFlowType container, Content c, Node n2, DataFlowType content +) { + readStep(n1, c, n2) and + container = getErasedNodeTypeBound(n1) and + content = getErasedNodeTypeBound(n2) +} -private class ContentOption extends TContentOption { - Content getContent() { this = TContentSome(result) } +private newtype TReadStepTypesOption = + TReadStepTypesNone() or + TReadStepTypesSome(DataFlowType container, Content c, DataFlowType content) { + readStepWithTypes(_, container, c, _, content) + } - predicate hasContent() { exists(this.getContent()) } +private class ReadStepTypesOption extends TReadStepTypesOption { + predicate isSome() { this instanceof TReadStepTypesSome } - string toString() { - result = this.getContent().toString() - or - not this.hasContent() and - result = "" - } + DataFlowType getContainerType() { this = TReadStepTypesSome(result, _, _) } + + Content getContent() { this = TReadStepTypesSome(_, result, _) } + + DataFlowType getContentType() { this = TReadStepTypesSome(_, _, result) } + + string toString() { if this.isSome() then result = "Some(..)" else result = "None()" } } /** diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index d65e33bffbb5..1f42c21d5a73 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -198,126 +198,130 @@ private module Cached { /** * The final flow-through calculation: * - * - Input access paths are abstracted with a `ContentOption` parameter - * that represents the head of the access path. `TContentNone()` means that - * the access path is unrestricted. + * - Calculated flow is either value-preserving (`read = TReadStepTypesNone()`) + * or summarized as a single read step with before and after types recorded + * in the `ReadStepTypesOption` parameter. * - Types are checked using the `compatibleTypes()` relation. */ private module Final { /** * Holds if `p` can flow to `node` in the same callable using only - * value-preserving steps, not taking call contexts into account. + * value-preserving steps and possibly a single read step, not taking + * call contexts into account. * - * `contentIn` describes the content of `p` that can flow to `node` - * (if any), `t2` is the type of the tracked value, and `t1` is the - * type before reading `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ - predicate parameterValueFlow( - ParameterNode p, Node node, ContentOption contentIn, DataFlowType t1, DataFlowType t2 - ) { - parameterValueFlow0(p, node, contentIn, t1, t2) and + predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) { + parameterValueFlow0(p, node, read) and if node instanceof CastingNode - then compatibleTypes(t2, getErasedNodeTypeBound(node)) + then + // normal flow through + read = TReadStepTypesNone() and + compatibleTypes(getErasedNodeTypeBound(p), getErasedNodeTypeBound(node)) + or + // getter + compatibleTypes(read.getContentType(), getErasedNodeTypeBound(node)) else any() } pragma[nomagic] - private predicate parameterValueFlow0( - ParameterNode p, Node node, ContentOption contentIn, DataFlowType t1, DataFlowType t2 - ) { + private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) { p = node and Cand::cand(p, _) and - contentIn = TContentNone() and - t1 = getErasedNodeTypeBound(p) and - t2 = t1 + read = TReadStepTypesNone() or // local flow exists(Node mid | - parameterValueFlow(p, mid, contentIn, t1, t2) and + parameterValueFlow(p, mid, read) and LocalFlowBigStep::localFlowBigStep(mid, node) ) or // read exists(Node mid | - parameterValueFlow(p, mid, TContentNone(), _, t1) and - readStep(mid, contentIn.getContent(), node) and + parameterValueFlow(p, mid, TReadStepTypesNone()) and + readStepWithTypes(mid, read.getContainerType(), read.getContent(), node, + read.getContentType()) and Cand::parameterValueFlowReturnCand(p, _, true) and - compatibleTypes(t1, getErasedNodeTypeBound(mid)) and - t2 = getErasedNodeTypeBound(node) + compatibleTypes(getErasedNodeTypeBound(p), read.getContainerType()) ) or // flow through: no prior read - exists(ArgumentNode arg, DataFlowType t0_, DataFlowType t1_, DataFlowType t2_ | - parameterValueFlowArg(p, arg, TContentNone(), _, t0_) and - argumentValueFlowsThrough(arg, contentIn, node, t1_, t2_) and - if contentIn = TContentNone() - then t1 = t0_ and t2 = t1 - else ( - t1 = t1_ and - t2 = t2_ - ) + exists(ArgumentNode arg | + parameterValueFlowArg(p, arg, TReadStepTypesNone()) and + argumentValueFlowsThrough(arg, read, node) ) or // flow through: no read inside method exists(ArgumentNode arg | - parameterValueFlowArg(p, arg, contentIn, t1, t2) and - argumentValueFlowsThrough(arg, TContentNone(), node, _, _) + parameterValueFlowArg(p, arg, read) and + argumentValueFlowsThrough(arg, TReadStepTypesNone(), node) ) } pragma[nomagic] private predicate parameterValueFlowArg( - ParameterNode p, ArgumentNode arg, ContentOption contentIn, DataFlowType t1, DataFlowType t2 + ParameterNode p, ArgumentNode arg, ReadStepTypesOption read ) { - parameterValueFlow(p, arg, contentIn, t1, t2) and + parameterValueFlow(p, arg, read) and Cand::argumentValueFlowsThroughCand(arg, _, _) } pragma[nomagic] private predicate argumentValueFlowsThrough0( - DataFlowCall call, ArgumentNode arg, ReturnKind kind, ContentOption contentIn, - DataFlowType t1, DataFlowType t2 + DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read ) { exists(ParameterNode param | viableParamArg(call, param, arg) | - parameterValueFlowReturn(param, kind, contentIn, t1, t2) + parameterValueFlowReturn(param, kind, read) ) } /** - * Holds if `arg` flows to `out` through a call using only value-preserving steps, - * not taking call contexts into account. + * Holds if `arg` flows to `out` through a call using only + * value-preserving steps and possibly a single read step, not taking + * call contexts into account. * - * `contentIn` describes the content of `arg` that can flow to `out` (if any), - * `t2` is the type of the tracked value, and `t1` is the type before reading - * `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ pragma[nomagic] - predicate argumentValueFlowsThrough( - ArgumentNode arg, ContentOption contentIn, Node out, DataFlowType t1, DataFlowType t2 - ) { + predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) { exists(DataFlowCall call, ReturnKind kind | - argumentValueFlowsThrough0(call, arg, kind, contentIn, t1, t2) and - out = getAnOutNode(call, kind) and - compatibleTypes(t2, getErasedNodeTypeBound(out)) and - if contentIn = TContentNone() - then compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out)) - else compatibleTypes(getErasedNodeTypeBound(arg), t1) + argumentValueFlowsThrough0(call, arg, kind, read) and + out = getAnOutNode(call, kind) + | + // normal flow through + read = TReadStepTypesNone() and + compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out)) + or + // getter + compatibleTypes(getErasedNodeTypeBound(arg), read.getContainerType()) and + compatibleTypes(read.getContentType(), getErasedNodeTypeBound(out)) ) } + /** + * Holds if `arg` flows to `out` through a call using only + * value-preserving steps and a single read step, not taking call + * contexts into account, thus representing a getter-step. + */ + predicate getterStep(ArgumentNode arg, Content c, Node out) { + argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out) + } + /** * Holds if `p` can flow to a return node of kind `kind` in the same - * callable using only value-preserving steps. + * callable using only value-preserving steps and possibly a single read + * step. * - * `contentIn` describes the content of `p` that can flow to the return - * node (if any), `t2` is the type of the tracked value, and `t1` is the - * type before reading `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ private predicate parameterValueFlowReturn( - ParameterNode p, ReturnKind kind, ContentOption contentIn, DataFlowType t1, DataFlowType t2 + ParameterNode p, ReturnKind kind, ReadStepTypesOption read ) { exists(ReturnNode ret | - parameterValueFlow(p, ret, contentIn, t1, t2) and + parameterValueFlow(p, ret, read) and kind = ret.getKind() ) } @@ -332,21 +336,25 @@ private module Cached { */ cached predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) { - parameterValueFlow(p, n.getPreUpdateNode(), TContentNone(), _, _) + parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone()) } - private predicate store(Node node1, Content c, Node node2, DataFlowType containerType) { + private predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { storeStep(node1, c, node2) and readStep(_, c, _) and + contentType = getErasedNodeTypeBound(node1) and containerType = getErasedNodeTypeBound(node2) or exists(Node n1, Node n2 | n1 = node1.(PostUpdateNode).getPreUpdateNode() and n2 = node2.(PostUpdateNode).getPreUpdateNode() | - argumentValueFlowsThrough(n2, TContentSome(c), n1, containerType, _) + argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1) or readStep(n2, c, n1) and + contentType = getErasedNodeTypeBound(n1) and containerType = getErasedNodeTypeBound(n2) ) } @@ -359,8 +367,8 @@ private module Cached { * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2) { - store(node1, tc.getContent(), node2, tc.getContainerType()) + predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { + store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) } import FlowThrough @@ -408,7 +416,7 @@ private module Cached { TBooleanSome(boolean b) { b = true or b = false } cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, t) } + newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } cached newtype TAccessPathFront = @@ -436,21 +444,30 @@ class CastingNode extends Node { } } -newtype TContentOption = - TContentNone() or - TContentSome(Content c) +private predicate readStepWithTypes( + Node n1, DataFlowType container, Content c, Node n2, DataFlowType content +) { + readStep(n1, c, n2) and + container = getErasedNodeTypeBound(n1) and + content = getErasedNodeTypeBound(n2) +} -private class ContentOption extends TContentOption { - Content getContent() { this = TContentSome(result) } +private newtype TReadStepTypesOption = + TReadStepTypesNone() or + TReadStepTypesSome(DataFlowType container, Content c, DataFlowType content) { + readStepWithTypes(_, container, c, _, content) + } - predicate hasContent() { exists(this.getContent()) } +private class ReadStepTypesOption extends TReadStepTypesOption { + predicate isSome() { this instanceof TReadStepTypesSome } - string toString() { - result = this.getContent().toString() - or - not this.hasContent() and - result = "" - } + DataFlowType getContainerType() { this = TReadStepTypesSome(result, _, _) } + + Content getContent() { this = TReadStepTypesSome(_, result, _) } + + DataFlowType getContentType() { this = TReadStepTypesSome(_, _, result) } + + string toString() { if this.isSome() then result = "Some(..)" else result = "None()" } } /** diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 8c3f4dab32d0..b7d076eff679 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -289,7 +289,7 @@ private predicate nodeCandFwd1(Node node, boolean fromArg, Configuration config) exists(Node mid | useFieldFlow(config) and nodeCandFwd1(mid, fromArg, config) and - store(mid, _, node) and + store(mid, _, node, _) and not outBarrier(mid, config) ) or @@ -337,7 +337,7 @@ private predicate nodeCandFwd1IsStored(Content c, Configuration config) { not fullBarrier(node, config) and useFieldFlow(config) and nodeCandFwd1(mid, config) and - store(mid, tc, node) and + store(mid, tc, node, _) and c = tc.getContent() ) } @@ -469,7 +469,7 @@ private predicate nodeCand1Store(Content c, Node node, boolean toReturn, Configu exists(Node mid, TypedContent tc | nodeCand1(mid, toReturn, config) and nodeCandFwd1IsStored(c, unbind(config)) and - store(node, tc, mid) and + store(node, tc, mid, _) and c = tc.getContent() ) } @@ -571,11 +571,11 @@ private predicate parameterThroughFlowNodeCand1(ParameterNode p, Configuration c } pragma[nomagic] -private predicate store(Node n1, Content c, Node n2, Configuration config) { +private predicate storeCand1(Node n1, Content c, Node n2, Configuration config) { exists(TypedContent tc | nodeCand1IsReadAndStored(c, config) and nodeCand1(n2, unbind(config)) and - store(n1, tc, n2) and + store(n1, tc, n2, _) and c = tc.getContent() ) } @@ -758,7 +758,7 @@ private predicate nodeCandFwd2( // store exists(Node mid | nodeCandFwd2(mid, fromArg, argStored, _, config) and - store(mid, _, node, config) and + storeCand1(mid, _, node, config) and stored = true ) or @@ -797,7 +797,7 @@ private predicate nodeCandFwd2IsStored(Content c, boolean stored, Configuration useFieldFlow(config) and nodeCand1(node, unbind(config)) and nodeCandFwd2(mid, _, _, stored, config) and - store(mid, c, node, config) + storeCand1(mid, c, node, config) ) } @@ -957,7 +957,7 @@ private predicate nodeCand2Store( Configuration config ) { exists(Node mid | - store(node, c, mid, config) and + storeCand1(node, c, mid, config) and nodeCand2(mid, toReturn, returnRead, true, config) and nodeCandFwd2(node, _, _, stored, unbind(config)) ) @@ -1066,7 +1066,7 @@ private module LocalFlowBigStep { additionalJumpStep(_, node, config) or node instanceof ParameterNode or node instanceof OutNodeExt or - store(_, _, node) or + store(_, _, node, _) or read(_, _, node) or node instanceof CastNode ) @@ -1082,7 +1082,7 @@ private module LocalFlowBigStep { additionalJumpStep(node, next, config) or flowIntoCallNodeCand1(_, node, next, config) or flowOutOfCallNodeCand1(_, node, next, config) or - store(node, _, next) or + store(node, _, next, _) or read(node, _, next) ) or @@ -1170,8 +1170,10 @@ private predicate readCand2(Node node1, Content c, Node node2, Configuration con } pragma[nomagic] -private predicate storeCand2(Node node1, TypedContent tc, Node node2, Configuration config) { - store(node1, tc, node2) and +private predicate storeCand2( + Node node1, TypedContent tc, Node node2, DataFlowType contentType, Configuration config +) { + store(node1, tc, node2, contentType) and nodeCand2(node1, config) and nodeCand2(node2, _, _, true, unbind(config)) and nodeCand2IsReadAndStored(tc.getContent(), unbind(config)) @@ -1235,11 +1237,12 @@ private predicate flowCandFwd0( ) or // store - exists(Node mid, TypedContent tc | - flowCandFwd(mid, fromArg, argApf, _, config) and - storeCand2(mid, tc, node, config) and + exists(Node mid, TypedContent tc, AccessPathFront apf0, DataFlowType contentType | + flowCandFwd(mid, fromArg, argApf, apf0, config) and + storeCand2(mid, tc, node, contentType, config) and nodeCand2(node, _, _, true, unbind(config)) and - apf.headUsesContent(tc) + apf.headUsesContent(tc) and + compatibleTypes(apf0.getType(), contentType) ) or // read @@ -1270,11 +1273,11 @@ private predicate flowCandFwd0( pragma[nomagic] private predicate flowCandFwdConsCand(TypedContent tc, AccessPathFront apf, Configuration config) { - exists(Node mid, Node n | + exists(Node mid, Node n, DataFlowType contentType | flowCandFwd(mid, _, _, apf, config) and - storeCand2(mid, tc, n, config) and + storeCand2(mid, tc, n, contentType, config) and nodeCand2(n, _, _, true, unbind(config)) and - compatibleTypes(apf.getType(), mid.getTypeBound()) + compatibleTypes(apf.getType(), contentType) ) } @@ -1454,7 +1457,7 @@ private predicate flowCandStore( ) { exists(Node mid | flowCandFwd(node, _, _, apf, config) and - storeCand2(node, tc, mid, unbind(config)) and + storeCand2(node, tc, mid, _, unbind(config)) and flowCand(mid, toReturn, returnApf, TFrontHead(tc), unbind(config)) ) } @@ -1737,7 +1740,7 @@ private predicate storeCand( Node mid, TypedContent tc, Node node, AccessPathFront apf0, AccessPathFront apf, Configuration config ) { - storeCand2(mid, tc, node, config) and + storeCand2(mid, tc, node, _, config) and flowCand(mid, _, _, apf0, config) and apf.headUsesContent(tc) } @@ -1919,7 +1922,7 @@ pragma[nomagic] private predicate storeFlowFwd( Node node1, TypedContent tc, Node node2, AccessPath ap, AccessPath ap0, Configuration config ) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flowFwdStore(node2, tc, ap, _, _, _, config) and ap0 = push(tc, ap) } @@ -2307,7 +2310,7 @@ private predicate pathReadStep( pragma[nomagic] private predicate storeCand(Node node1, TypedContent tc, Node node2, Configuration config) { - storeCand2(node1, tc, node2, config) and + storeCand2(node1, tc, node2, _, config) and flow(node2, config) } @@ -2799,13 +2802,13 @@ private module FlowExploration { PartialPathNodePriv mid, PartialAccessPath ap1, TypedContent tc, Node node, PartialAccessPath ap2 ) { - exists(Node midNode | + exists(Node midNode, DataFlowType contentType | midNode = mid.getNode() and ap1 = mid.getAp() and - store(midNode, tc, node) and + store(midNode, tc, node, contentType) and ap2.getHead() = tc and ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), getErasedNodeTypeBound(midNode)) + compatibleTypes(ap1.getType(), contentType) ) } @@ -2830,8 +2833,7 @@ private module FlowExploration { read(midNode, tc.getContent(), node) and ap.getHead() = tc and config = mid.getConfiguration() and - cc = mid.getCallContext() and - compatibleTypes(tc.getContainerType(), getErasedNodeTypeBound(midNode)) + cc = mid.getCallContext() ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index d65e33bffbb5..1f42c21d5a73 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -198,126 +198,130 @@ private module Cached { /** * The final flow-through calculation: * - * - Input access paths are abstracted with a `ContentOption` parameter - * that represents the head of the access path. `TContentNone()` means that - * the access path is unrestricted. + * - Calculated flow is either value-preserving (`read = TReadStepTypesNone()`) + * or summarized as a single read step with before and after types recorded + * in the `ReadStepTypesOption` parameter. * - Types are checked using the `compatibleTypes()` relation. */ private module Final { /** * Holds if `p` can flow to `node` in the same callable using only - * value-preserving steps, not taking call contexts into account. + * value-preserving steps and possibly a single read step, not taking + * call contexts into account. * - * `contentIn` describes the content of `p` that can flow to `node` - * (if any), `t2` is the type of the tracked value, and `t1` is the - * type before reading `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ - predicate parameterValueFlow( - ParameterNode p, Node node, ContentOption contentIn, DataFlowType t1, DataFlowType t2 - ) { - parameterValueFlow0(p, node, contentIn, t1, t2) and + predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) { + parameterValueFlow0(p, node, read) and if node instanceof CastingNode - then compatibleTypes(t2, getErasedNodeTypeBound(node)) + then + // normal flow through + read = TReadStepTypesNone() and + compatibleTypes(getErasedNodeTypeBound(p), getErasedNodeTypeBound(node)) + or + // getter + compatibleTypes(read.getContentType(), getErasedNodeTypeBound(node)) else any() } pragma[nomagic] - private predicate parameterValueFlow0( - ParameterNode p, Node node, ContentOption contentIn, DataFlowType t1, DataFlowType t2 - ) { + private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) { p = node and Cand::cand(p, _) and - contentIn = TContentNone() and - t1 = getErasedNodeTypeBound(p) and - t2 = t1 + read = TReadStepTypesNone() or // local flow exists(Node mid | - parameterValueFlow(p, mid, contentIn, t1, t2) and + parameterValueFlow(p, mid, read) and LocalFlowBigStep::localFlowBigStep(mid, node) ) or // read exists(Node mid | - parameterValueFlow(p, mid, TContentNone(), _, t1) and - readStep(mid, contentIn.getContent(), node) and + parameterValueFlow(p, mid, TReadStepTypesNone()) and + readStepWithTypes(mid, read.getContainerType(), read.getContent(), node, + read.getContentType()) and Cand::parameterValueFlowReturnCand(p, _, true) and - compatibleTypes(t1, getErasedNodeTypeBound(mid)) and - t2 = getErasedNodeTypeBound(node) + compatibleTypes(getErasedNodeTypeBound(p), read.getContainerType()) ) or // flow through: no prior read - exists(ArgumentNode arg, DataFlowType t0_, DataFlowType t1_, DataFlowType t2_ | - parameterValueFlowArg(p, arg, TContentNone(), _, t0_) and - argumentValueFlowsThrough(arg, contentIn, node, t1_, t2_) and - if contentIn = TContentNone() - then t1 = t0_ and t2 = t1 - else ( - t1 = t1_ and - t2 = t2_ - ) + exists(ArgumentNode arg | + parameterValueFlowArg(p, arg, TReadStepTypesNone()) and + argumentValueFlowsThrough(arg, read, node) ) or // flow through: no read inside method exists(ArgumentNode arg | - parameterValueFlowArg(p, arg, contentIn, t1, t2) and - argumentValueFlowsThrough(arg, TContentNone(), node, _, _) + parameterValueFlowArg(p, arg, read) and + argumentValueFlowsThrough(arg, TReadStepTypesNone(), node) ) } pragma[nomagic] private predicate parameterValueFlowArg( - ParameterNode p, ArgumentNode arg, ContentOption contentIn, DataFlowType t1, DataFlowType t2 + ParameterNode p, ArgumentNode arg, ReadStepTypesOption read ) { - parameterValueFlow(p, arg, contentIn, t1, t2) and + parameterValueFlow(p, arg, read) and Cand::argumentValueFlowsThroughCand(arg, _, _) } pragma[nomagic] private predicate argumentValueFlowsThrough0( - DataFlowCall call, ArgumentNode arg, ReturnKind kind, ContentOption contentIn, - DataFlowType t1, DataFlowType t2 + DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read ) { exists(ParameterNode param | viableParamArg(call, param, arg) | - parameterValueFlowReturn(param, kind, contentIn, t1, t2) + parameterValueFlowReturn(param, kind, read) ) } /** - * Holds if `arg` flows to `out` through a call using only value-preserving steps, - * not taking call contexts into account. + * Holds if `arg` flows to `out` through a call using only + * value-preserving steps and possibly a single read step, not taking + * call contexts into account. * - * `contentIn` describes the content of `arg` that can flow to `out` (if any), - * `t2` is the type of the tracked value, and `t1` is the type before reading - * `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ pragma[nomagic] - predicate argumentValueFlowsThrough( - ArgumentNode arg, ContentOption contentIn, Node out, DataFlowType t1, DataFlowType t2 - ) { + predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) { exists(DataFlowCall call, ReturnKind kind | - argumentValueFlowsThrough0(call, arg, kind, contentIn, t1, t2) and - out = getAnOutNode(call, kind) and - compatibleTypes(t2, getErasedNodeTypeBound(out)) and - if contentIn = TContentNone() - then compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out)) - else compatibleTypes(getErasedNodeTypeBound(arg), t1) + argumentValueFlowsThrough0(call, arg, kind, read) and + out = getAnOutNode(call, kind) + | + // normal flow through + read = TReadStepTypesNone() and + compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out)) + or + // getter + compatibleTypes(getErasedNodeTypeBound(arg), read.getContainerType()) and + compatibleTypes(read.getContentType(), getErasedNodeTypeBound(out)) ) } + /** + * Holds if `arg` flows to `out` through a call using only + * value-preserving steps and a single read step, not taking call + * contexts into account, thus representing a getter-step. + */ + predicate getterStep(ArgumentNode arg, Content c, Node out) { + argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out) + } + /** * Holds if `p` can flow to a return node of kind `kind` in the same - * callable using only value-preserving steps. + * callable using only value-preserving steps and possibly a single read + * step. * - * `contentIn` describes the content of `p` that can flow to the return - * node (if any), `t2` is the type of the tracked value, and `t1` is the - * type before reading `contentIn` (`= t2` when no content is read). + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. */ private predicate parameterValueFlowReturn( - ParameterNode p, ReturnKind kind, ContentOption contentIn, DataFlowType t1, DataFlowType t2 + ParameterNode p, ReturnKind kind, ReadStepTypesOption read ) { exists(ReturnNode ret | - parameterValueFlow(p, ret, contentIn, t1, t2) and + parameterValueFlow(p, ret, read) and kind = ret.getKind() ) } @@ -332,21 +336,25 @@ private module Cached { */ cached predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) { - parameterValueFlow(p, n.getPreUpdateNode(), TContentNone(), _, _) + parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone()) } - private predicate store(Node node1, Content c, Node node2, DataFlowType containerType) { + private predicate store( + Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType + ) { storeStep(node1, c, node2) and readStep(_, c, _) and + contentType = getErasedNodeTypeBound(node1) and containerType = getErasedNodeTypeBound(node2) or exists(Node n1, Node n2 | n1 = node1.(PostUpdateNode).getPreUpdateNode() and n2 = node2.(PostUpdateNode).getPreUpdateNode() | - argumentValueFlowsThrough(n2, TContentSome(c), n1, containerType, _) + argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1) or readStep(n2, c, n1) and + contentType = getErasedNodeTypeBound(n1) and containerType = getErasedNodeTypeBound(n2) ) } @@ -359,8 +367,8 @@ private module Cached { * been stored into, in order to handle cases like `x.f1.f2 = y`. */ cached - predicate store(Node node1, TypedContent tc, Node node2) { - store(node1, tc.getContent(), node2, tc.getContainerType()) + predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { + store(node1, tc.getContent(), node2, contentType, tc.getContainerType()) } import FlowThrough @@ -408,7 +416,7 @@ private module Cached { TBooleanSome(boolean b) { b = true or b = false } cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, t) } + newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } cached newtype TAccessPathFront = @@ -436,21 +444,30 @@ class CastingNode extends Node { } } -newtype TContentOption = - TContentNone() or - TContentSome(Content c) +private predicate readStepWithTypes( + Node n1, DataFlowType container, Content c, Node n2, DataFlowType content +) { + readStep(n1, c, n2) and + container = getErasedNodeTypeBound(n1) and + content = getErasedNodeTypeBound(n2) +} -private class ContentOption extends TContentOption { - Content getContent() { this = TContentSome(result) } +private newtype TReadStepTypesOption = + TReadStepTypesNone() or + TReadStepTypesSome(DataFlowType container, Content c, DataFlowType content) { + readStepWithTypes(_, container, c, _, content) + } - predicate hasContent() { exists(this.getContent()) } +private class ReadStepTypesOption extends TReadStepTypesOption { + predicate isSome() { this instanceof TReadStepTypesSome } - string toString() { - result = this.getContent().toString() - or - not this.hasContent() and - result = "" - } + DataFlowType getContainerType() { this = TReadStepTypesSome(result, _, _) } + + Content getContent() { this = TReadStepTypesSome(_, result, _) } + + DataFlowType getContentType() { this = TReadStepTypesSome(_, _, result) } + + string toString() { if this.isSome() then result = "Some(..)" else result = "None()" } } /** diff --git a/java/ql/test/library-tests/dataflow/getter/getter.ql b/java/ql/test/library-tests/dataflow/getter/getter.ql index 7188a05540bb..02e6920fc7e6 100644 --- a/java/ql/test/library-tests/dataflow/getter/getter.ql +++ b/java/ql/test/library-tests/dataflow/getter/getter.ql @@ -6,5 +6,5 @@ import semmle.code.java.dataflow.internal.DataFlowImplSpecific::Private from Node n1, Content f, Node n2 where read(n1, f, n2) or - argumentValueFlowsThrough(n1, TContentSome(f), n2, _, _) + getterStep(n1, f, n2) select n1, n2, f