From 14cfb82a8c16e15fadc006ae46331302f0341f63 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 30 Oct 2023 10:47:29 +0100 Subject: [PATCH 1/3] Ruby: Summarized type-tracking stores should target post-update nodes --- .../dataflow/internal/DataFlowPrivate.qll | 6 +- .../ruby/typetracking/TypeTrackerSpecific.qll | 16 ++-- .../internal/SummaryTypeTracker.qll | 56 ++++++----- .../type-tracking-array-flow.expected | 95 ------------------- .../type-tracking-hash-flow.expected | 3 - .../dataflow/params/TypeTracker.expected | 6 +- .../type-tracker/TypeTracker.expected | 28 +++++- 7 files changed, 73 insertions(+), 137 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index d9a0ad2c6c9c..5ee2dbd3f462 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -596,11 +596,11 @@ private module Cached { entrySsaDefinition(n) and not LocalFlow::localFlowSsaParamInput(_, n) or - TypeTrackerSpecific::storeStepIntoSourceNode(_, n, _) + TypeTrackerSpecific::basicStoreStep(_, n, _) or - TypeTrackerSpecific::readStepIntoSourceNode(_, n, _) + TypeTrackerSpecific::basicLoadStep(_, n, _) or - TypeTrackerSpecific::readStoreStepIntoSourceNode(_, n, _, _) + TypeTrackerSpecific::basicLoadStoreStep(_, n, _, _) } cached diff --git a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll index 73a4de4c3601..d0ca089f6bc5 100644 --- a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll @@ -275,7 +275,7 @@ predicate basicStoreStep(Node nodeFrom, Node nodeTo, DataFlow::ContentSet conten * Holds if a store step `nodeFrom -> nodeTo` with `contents` exists, where the destination node * is a post-update node that should be treated as a local source node. */ -predicate storeStepIntoSourceNode(Node nodeFrom, Node nodeTo, DataFlow::ContentSet contents) { +private predicate storeStepIntoSourceNode(Node nodeFrom, Node nodeTo, DataFlow::ContentSet contents) { // TODO: support SetterMethodCall inside TuplePattern exists(ExprNodes::MethodCallCfgNode call | contents @@ -311,7 +311,7 @@ predicate basicLoadStep(Node nodeFrom, Node nodeTo, DataFlow::ContentSet content * Holds if a read step `nodeFrom -> nodeTo` with `contents` exists, where the destination node * should be treated as a local source node. */ -predicate readStepIntoSourceNode(Node nodeFrom, Node nodeTo, DataFlow::ContentSet contents) { +private predicate readStepIntoSourceNode(Node nodeFrom, Node nodeTo, DataFlow::ContentSet contents) { DataFlowPrivate::readStepCommon(nodeFrom, contents, nodeTo) } @@ -330,7 +330,7 @@ predicate basicLoadStoreStep( * Holds if a read+store step `nodeFrom -> nodeTo` exists, where the destination node * should be treated as a local source node. */ -predicate readStoreStepIntoSourceNode( +private predicate readStoreStepIntoSourceNode( Node nodeFrom, Node nodeTo, DataFlow::ContentSet loadContent, DataFlow::ContentSet storeContent ) { exists(DataFlowPrivate::SynthSplatParameterShiftNode shift | @@ -441,10 +441,14 @@ private module SummaryTypeTrackerInput implements SummaryTypeTracker::Input { class SummarizedCallable = FlowSummary::SummarizedCallable; // Relating nodes to summaries - Node argumentOf(Node call, SummaryComponent arg) { - exists(DataFlowDispatch::ParameterPosition pos | + Node argumentOf(Node call, SummaryComponent arg, boolean isPostUpdate) { + exists(DataFlowDispatch::ParameterPosition pos, DataFlowPrivate::ArgumentNode n | arg = SummaryComponent::argument(pos) and - argumentPositionMatch(call.asExpr(), result, pos) + argumentPositionMatch(call.asExpr(), n, pos) + | + isPostUpdate = false and result = n + or + isPostUpdate = true and result.(DataFlowPublic::PostUpdateNode).getPreUpdateNode() = n ) } diff --git a/ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll b/ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll index 9c6f841651dd..9754838be61e 100644 --- a/ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll +++ b/ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll @@ -74,7 +74,7 @@ signature module Input { // Relating nodes to summaries /** Gets a dataflow node respresenting the argument of `call` indicated by `arg`. */ - Node argumentOf(Node call, SummaryComponent arg); + Node argumentOf(Node call, SummaryComponent arg, boolean isOutput); /** Gets a dataflow node respresenting the parameter of `callable` indicated by `param`. */ Node parameterOf(Node callable, SummaryComponent param); @@ -224,11 +224,14 @@ module SummaryFlow implements Output { * as specified by `component`. */ bindingset[call, component] - private I::Node evaluateSummaryComponentLocal(I::Node call, I::SummaryComponent component) { - result = I::argumentOf(call, component) + private I::Node evaluateSummaryComponentLocal( + I::Node call, I::SummaryComponent component, boolean isOutput + ) { + result = I::argumentOf(call, component, isOutput) or component = I::return() and - result = call + result = call and + isOutput = true } /** @@ -280,27 +283,34 @@ module SummaryFlow implements Output { */ pragma[nomagic] private I::Node evaluateSummaryComponentStackLocal( - I::SummarizedCallable callable, I::Node call, I::SummaryComponentStack stack + I::SummarizedCallable callable, I::Node call, I::SummaryComponentStack stack, boolean isOutput ) { exists(I::SummaryComponent component | dependsOnSummaryComponentStackLeaf(callable, component) and stack = I::singleton(component) and call = I::callTo(callable) and - result = evaluateSummaryComponentLocal(call, component) + result = evaluateSummaryComponentLocal(call, component, isOutput) ) or - exists(I::Node prev, I::SummaryComponent head, I::SummaryComponentStack tail | - prev = evaluateSummaryComponentStackLocal(callable, call, tail) and + exists( + I::Node prev, I::SummaryComponent head, I::SummaryComponentStack tail, boolean isOutput0 + | + prev = evaluateSummaryComponentStackLocal(callable, call, tail, isOutput0) and dependsOnSummaryComponentStackConsLocal(callable, pragma[only_bind_into](head), pragma[only_bind_out](tail)) and stack = I::push(pragma[only_bind_out](head), pragma[only_bind_out](tail)) | - result = I::parameterOf(prev, head) + result = I::parameterOf(prev, head) and + isOutput0 = false and + isOutput = true or - result = I::returnOf(prev, head) + result = I::returnOf(prev, head) and + isOutput0 = false and + isOutput = false or componentLevelStep(head) and - result = prev + result = prev and + isOutput = isOutput0 ) } @@ -312,8 +322,8 @@ module SummaryFlow implements Output { | callable.propagatesFlow(input, output, true) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } @@ -325,8 +335,8 @@ module SummaryFlow implements Output { hasLoadSummary(callable, content, pragma[only_bind_into](input), pragma[only_bind_into](output)) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } @@ -338,8 +348,8 @@ module SummaryFlow implements Output { hasStoreSummary(callable, content, pragma[only_bind_into](input), pragma[only_bind_into](output)) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } @@ -354,8 +364,8 @@ module SummaryFlow implements Output { hasLoadStoreSummary(callable, loadContent, storeContent, pragma[only_bind_into](input), pragma[only_bind_into](output)) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } @@ -369,8 +379,8 @@ module SummaryFlow implements Output { hasWithoutContentSummary(callable, filter, pragma[only_bind_into](input), pragma[only_bind_into](output)) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } @@ -384,8 +394,8 @@ module SummaryFlow implements Output { hasWithContentSummary(callable, filter, pragma[only_bind_into](input), pragma[only_bind_into](output)) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } } diff --git a/ruby/ql/test/library-tests/dataflow/array-flow/type-tracking-array-flow.expected b/ruby/ql/test/library-tests/dataflow/array-flow/type-tracking-array-flow.expected index 4352b9471cf8..31c5b4a28666 100644 --- a/ruby/ql/test/library-tests/dataflow/array-flow/type-tracking-array-flow.expected +++ b/ruby/ql/test/library-tests/dataflow/array-flow/type-tracking-array-flow.expected @@ -3,26 +3,14 @@ testFailures | array_flow.rb:179:28:179:46 | # $ hasValueFlow=19 | Missing result:hasValueFlow=19 | | array_flow.rb:180:28:180:46 | # $ hasValueFlow=19 | Missing result:hasValueFlow=19 | | array_flow.rb:226:10:226:13 | ...[...] | Unexpected result: hasValueFlow=25 | -| array_flow.rb:242:14:242:14 | x | Unexpected result: hasValueFlow=27.2 | | array_flow.rb:319:10:319:13 | ...[...] | Unexpected result: hasValueFlow=36.1 | | array_flow.rb:320:10:320:13 | ...[...] | Unexpected result: hasValueFlow=36.1 | | array_flow.rb:321:10:321:13 | ...[...] | Unexpected result: hasValueFlow=36.1 | -| array_flow.rb:327:10:327:10 | b | Unexpected result: hasValueFlow=37.2 | | array_flow.rb:328:10:328:13 | ...[...] | Unexpected result: hasValueFlow=37.1 | | array_flow.rb:360:22:360:42 | # $ hasValueFlow=40.2 | Missing result:hasValueFlow=40.2 | -| array_flow.rb:374:10:374:13 | ...[...] | Unexpected result: hasValueFlow=42.3 | -| array_flow.rb:376:10:376:13 | ...[...] | Unexpected result: hasValueFlow=42.3 | -| array_flow.rb:377:10:377:13 | ...[...] | Unexpected result: hasValueFlow=42.3 | -| array_flow.rb:378:10:378:13 | ...[...] | Unexpected result: hasValueFlow=42.3 | -| array_flow.rb:484:10:484:13 | ...[...] | Unexpected result: hasValueFlow=54.3 | -| array_flow.rb:484:10:484:13 | ...[...] | Unexpected result: hasValueFlow=54.4 | -| array_flow.rb:484:10:484:13 | ...[...] | Unexpected result: hasValueFlow=54.5 | | array_flow.rb:486:10:486:13 | ...[...] | Unexpected result: hasValueFlow=54.2 | -| array_flow.rb:486:10:486:13 | ...[...] | Unexpected result: hasValueFlow=54.4 | -| array_flow.rb:486:10:486:13 | ...[...] | Unexpected result: hasValueFlow=54.5 | | array_flow.rb:490:10:490:13 | ...[...] | Unexpected result: hasValueFlow=54.2 | | array_flow.rb:490:10:490:13 | ...[...] | Unexpected result: hasValueFlow=54.3 | -| array_flow.rb:490:10:490:13 | ...[...] | Unexpected result: hasValueFlow=54.5 | | array_flow.rb:494:10:494:13 | ...[...] | Unexpected result: hasValueFlow=54.2 | | array_flow.rb:494:10:494:13 | ...[...] | Unexpected result: hasValueFlow=54.3 | | array_flow.rb:586:16:586:34 | # $ hasValueFlow=63 | Missing result:hasValueFlow=63 | @@ -31,43 +19,11 @@ testFailures | array_flow.rb:594:19:594:47 | # $ SPURIOUS: hasValueFlow=64 | Fixed spurious result:hasValueFlow=64 | | array_flow.rb:595:16:595:34 | # $ hasValueFlow=64 | Missing result:hasValueFlow=64 | | array_flow.rb:596:19:596:47 | # $ SPURIOUS: hasValueFlow=64 | Fixed spurious result:hasValueFlow=64 | -| array_flow.rb:657:10:657:13 | ...[...] | Unexpected result: hasValueFlow=70.1 | -| array_flow.rb:657:10:657:13 | ...[...] | Unexpected result: hasValueFlow=70.2 | -| array_flow.rb:657:10:657:13 | ...[...] | Unexpected result: hasValueFlow=70.3 | -| array_flow.rb:658:10:658:13 | ...[...] | Unexpected result: hasValueFlow=70.1 | -| array_flow.rb:658:10:658:13 | ...[...] | Unexpected result: hasValueFlow=70.3 | | array_flow.rb:659:10:659:13 | ...[...] | Unexpected result: hasValueFlow=70.1 | -| array_flow.rb:659:10:659:13 | ...[...] | Unexpected result: hasValueFlow=70.2 | -| array_flow.rb:660:10:660:13 | ...[...] | Unexpected result: hasValueFlow=70.1 | -| array_flow.rb:660:10:660:13 | ...[...] | Unexpected result: hasValueFlow=70.2 | -| array_flow.rb:660:10:660:13 | ...[...] | Unexpected result: hasValueFlow=70.3 | -| array_flow.rb:661:10:661:13 | ...[...] | Unexpected result: hasValueFlow=70.2 | -| array_flow.rb:661:10:661:13 | ...[...] | Unexpected result: hasValueFlow=70.3 | -| array_flow.rb:662:10:662:13 | ...[...] | Unexpected result: hasValueFlow=70.1 | -| array_flow.rb:662:10:662:13 | ...[...] | Unexpected result: hasValueFlow=70.2 | -| array_flow.rb:662:10:662:13 | ...[...] | Unexpected result: hasValueFlow=70.3 | -| array_flow.rb:663:10:663:13 | ...[...] | Unexpected result: hasValueFlow=70.1 | -| array_flow.rb:663:10:663:13 | ...[...] | Unexpected result: hasValueFlow=70.3 | | array_flow.rb:664:10:664:13 | ...[...] | Unexpected result: hasValueFlow=70.1 | -| array_flow.rb:664:10:664:13 | ...[...] | Unexpected result: hasValueFlow=70.2 | -| array_flow.rb:665:10:665:13 | ...[...] | Unexpected result: hasValueFlow=70.1 | -| array_flow.rb:665:10:665:13 | ...[...] | Unexpected result: hasValueFlow=70.2 | -| array_flow.rb:665:10:665:13 | ...[...] | Unexpected result: hasValueFlow=70.3 | -| array_flow.rb:666:10:666:13 | ...[...] | Unexpected result: hasValueFlow=70.2 | -| array_flow.rb:666:10:666:13 | ...[...] | Unexpected result: hasValueFlow=70.3 | -| array_flow.rb:719:14:719:14 | x | Unexpected result: hasValueFlow=76.2 | | array_flow.rb:871:18:871:36 | # $ hasValueFlow=87 | Missing result:hasValueFlow=87 | | array_flow.rb:872:18:872:36 | # $ hasValueFlow=87 | Missing result:hasValueFlow=87 | -| array_flow.rb:926:10:926:13 | ...[...] | Unexpected result: hasValueFlow=90.1 | -| array_flow.rb:926:10:926:13 | ...[...] | Unexpected result: hasValueFlow=90.2 | -| array_flow.rb:927:10:927:13 | ...[...] | Unexpected result: hasValueFlow=90.1 | -| array_flow.rb:927:10:927:13 | ...[...] | Unexpected result: hasValueFlow=90.2 | | array_flow.rb:928:10:928:13 | ...[...] | Unexpected result: hasValueFlow=90.1 | -| array_flow.rb:929:10:929:13 | ...[...] | Unexpected result: hasValueFlow=90.1 | -| array_flow.rb:929:10:929:13 | ...[...] | Unexpected result: hasValueFlow=90.2 | -| array_flow.rb:930:10:930:13 | ...[...] | Unexpected result: hasValueFlow=90.1 | -| array_flow.rb:930:10:930:13 | ...[...] | Unexpected result: hasValueFlow=90.2 | -| array_flow.rb:931:10:931:13 | ...[...] | Unexpected result: hasValueFlow=90.2 | | array_flow.rb:939:18:939:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.1 | | array_flow.rb:939:18:939:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.2 | | array_flow.rb:939:18:939:78 | # $ hasValueFlow=91.1 $ hasValueFlow=91.2 $ hasValueFlow=91.3 | Missing result:hasValueFlow=91.3 | @@ -77,82 +33,31 @@ testFailures | array_flow.rb:957:28:957:46 | # $ hasValueFlow=93 | Missing result:hasValueFlow=93 | | array_flow.rb:958:28:958:46 | # $ hasValueFlow=93 | Missing result:hasValueFlow=93 | | array_flow.rb:1018:16:1018:36 | # $ hasValueFlow=99.2 | Missing result:hasValueFlow=99.2 | -| array_flow.rb:1097:10:1097:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | -| array_flow.rb:1097:10:1097:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1098:10:1098:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | | array_flow.rb:1099:10:1099:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | -| array_flow.rb:1100:10:1100:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | | array_flow.rb:1100:10:1100:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1101:10:1101:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | -| array_flow.rb:1101:10:1101:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1102:10:1102:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1103:10:1103:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | -| array_flow.rb:1104:10:1104:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | -| array_flow.rb:1104:10:1104:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1108:10:1108:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1109:10:1109:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | | array_flow.rb:1110:10:1110:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | -| array_flow.rb:1110:10:1110:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1111:10:1111:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | | array_flow.rb:1111:10:1111:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1112:10:1112:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1113:10:1113:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | -| array_flow.rb:1114:10:1114:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | -| array_flow.rb:1114:10:1114:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1115:10:1115:13 | ...[...] | Unexpected result: hasValueFlow=105.2 | -| array_flow.rb:1115:10:1115:13 | ...[...] | Unexpected result: hasValueFlow=105.3 | -| array_flow.rb:1161:10:1161:10 | b | Unexpected result: hasValueFlow=108.2 | | array_flow.rb:1162:10:1162:13 | ...[...] | Unexpected result: hasValueFlow=108.1 | -| array_flow.rb:1162:10:1162:13 | ...[...] | Unexpected result: hasValueFlow=108.2 | | array_flow.rb:1164:10:1164:13 | ...[...] | Unexpected result: hasValueFlow=108.2 | -| array_flow.rb:1168:10:1168:13 | ...[...] | Unexpected result: hasValueFlow=108.2 | | array_flow.rb:1170:10:1170:13 | ...[...] | Unexpected result: hasValueFlow=108.1 | | array_flow.rb:1172:10:1172:13 | ...[...] | Unexpected result: hasValueFlow=108.2 | | array_flow.rb:1224:10:1224:13 | ...[...] | Unexpected result: hasValueFlow=111.1 | | array_flow.rb:1233:10:1233:13 | ...[...] | Unexpected result: hasValueFlow=111.1 | | array_flow.rb:1238:10:1238:13 | ...[...] | Unexpected result: hasValueFlow=111.1 | -| array_flow.rb:1262:10:1262:10 | b | Unexpected result: hasValueFlow=112.2 | | array_flow.rb:1265:10:1265:13 | ...[...] | Unexpected result: hasValueFlow=112.1 | -| array_flow.rb:1265:10:1265:13 | ...[...] | Unexpected result: hasValueFlow=112.2 | | array_flow.rb:1286:10:1286:13 | ...[...] | Unexpected result: hasValueFlow=112.1 | | array_flow.rb:1288:10:1288:13 | ...[...] | Unexpected result: hasValueFlow=112.2 | -| array_flow.rb:1292:10:1292:13 | ...[...] | Unexpected result: hasValueFlow=112.2 | | array_flow.rb:1297:10:1297:13 | ...[...] | Unexpected result: hasValueFlow=112.1 | | array_flow.rb:1299:10:1299:13 | ...[...] | Unexpected result: hasValueFlow=112.2 | -| array_flow.rb:1303:10:1303:13 | ...[...] | Unexpected result: hasValueFlow=112.2 | | array_flow.rb:1308:10:1308:13 | ...[...] | Unexpected result: hasValueFlow=112.1 | | array_flow.rb:1310:10:1310:13 | ...[...] | Unexpected result: hasValueFlow=112.2 | -| array_flow.rb:1342:10:1342:13 | ...[...] | Unexpected result: hasValueFlow=112.2 | | array_flow.rb:1346:10:1346:13 | ...[...] | Unexpected result: hasValueFlow=112.1 | -| array_flow.rb:1449:10:1449:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1450:10:1450:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1451:10:1451:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1452:10:1452:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1454:10:1454:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1455:10:1455:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1456:10:1456:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | | array_flow.rb:1457:10:1457:13 | ...[...] | Unexpected result: hasValueFlow=121.2 | -| array_flow.rb:1457:10:1457:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | | array_flow.rb:1458:10:1458:13 | ...[...] | Unexpected result: hasValueFlow=121.2 | -| array_flow.rb:1458:10:1458:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1460:10:1460:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1461:10:1461:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1462:10:1462:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1463:10:1463:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | -| array_flow.rb:1464:10:1464:13 | ...[...] | Unexpected result: hasValueFlow=121.3 | | array_flow.rb:1512:18:1512:39 | # $ hasValueFlow=128.1 | Missing result:hasValueFlow=128.1 | | array_flow.rb:1513:18:1513:39 | # $ hasValueFlow=128.2 | Missing result:hasValueFlow=128.2 | | array_flow.rb:1514:18:1514:39 | # $ hasValueFlow=128.3 | Missing result:hasValueFlow=128.3 | -| array_flow.rb:1563:10:1563:13 | ...[...] | Unexpected result: hasValueFlow=132.1 | -| array_flow.rb:1563:10:1563:13 | ...[...] | Unexpected result: hasValueFlow=132.2 | -| array_flow.rb:1564:10:1564:13 | ...[...] | Unexpected result: hasValueFlow=132.1 | -| array_flow.rb:1564:10:1564:13 | ...[...] | Unexpected result: hasValueFlow=132.2 | | array_flow.rb:1565:10:1565:13 | ...[...] | Unexpected result: hasValueFlow=132.1 | -| array_flow.rb:1566:10:1566:13 | ...[...] | Unexpected result: hasValueFlow=132.1 | -| array_flow.rb:1566:10:1566:13 | ...[...] | Unexpected result: hasValueFlow=132.2 | -| array_flow.rb:1567:10:1567:13 | ...[...] | Unexpected result: hasValueFlow=132.1 | -| array_flow.rb:1567:10:1567:13 | ...[...] | Unexpected result: hasValueFlow=132.2 | -| array_flow.rb:1568:10:1568:13 | ...[...] | Unexpected result: hasValueFlow=132.2 | | array_flow.rb:1601:18:1601:39 | # $ hasValueFlow=134.3 | Missing result:hasValueFlow=134.3 | | array_flow.rb:1602:18:1602:39 | # $ hasValueFlow=134.2 | Missing result:hasValueFlow=134.2 | | array_flow.rb:1603:18:1603:39 | # $ hasValueFlow=134.1 | Missing result:hasValueFlow=134.1 | diff --git a/ruby/ql/test/library-tests/dataflow/hash-flow/type-tracking-hash-flow.expected b/ruby/ql/test/library-tests/dataflow/hash-flow/type-tracking-hash-flow.expected index 7ffbd73ccbea..153b8f32d667 100644 --- a/ruby/ql/test/library-tests/dataflow/hash-flow/type-tracking-hash-flow.expected +++ b/ruby/ql/test/library-tests/dataflow/hash-flow/type-tracking-hash-flow.expected @@ -1,9 +1,7 @@ testFailures | hash_flow.rb:65:21:65:40 | # $ hasValueFlow=3.3 | Missing result:hasValueFlow=3.3 | | hash_flow.rb:66:21:66:49 | # $ SPURIOUS hasValueFlow=3.3 | Missing result:hasValueFlow=3.3 | -| hash_flow.rb:114:10:114:17 | ...[...] | Unexpected result: hasValueFlow=7.2 | | hash_flow.rb:117:10:117:17 | ...[...] | Unexpected result: hasValueFlow=7.1 | -| hash_flow.rb:117:10:117:17 | ...[...] | Unexpected result: hasValueFlow=7.2 | | hash_flow.rb:119:10:119:17 | ...[...] | Unexpected result: hasValueFlow=7.1 | | hash_flow.rb:152:16:152:36 | # $ hasValueFlow=10.1 | Missing result:hasValueFlow=10.1 | | hash_flow.rb:163:10:163:17 | ...[...] | Unexpected result: hasValueFlow=9.1 | @@ -22,7 +20,6 @@ testFailures | hash_flow.rb:571:18:571:38 | # $ hasValueFlow=35.1 | Missing result:hasValueFlow=35.1 | | hash_flow.rb:591:20:591:60 | # $ hasValueFlow=36.1 $ hasValueFlow=36.2 | Missing result:hasValueFlow=36.1 | | hash_flow.rb:591:20:591:60 | # $ hasValueFlow=36.1 $ hasValueFlow=36.2 | Missing result:hasValueFlow=36.2 | -| hash_flow.rb:670:14:670:18 | value | Unexpected result: hasValueFlow=41.3 | | hash_flow.rb:673:10:673:19 | ( ... ) | Unexpected result: hasValueFlow=41.1 | | hash_flow.rb:704:22:704:42 | # $ hasValueFlow=42.3 | Missing result:hasValueFlow=42.3 | | hash_flow.rb:706:22:706:42 | # $ hasValueFlow=42.4 | Missing result:hasValueFlow=42.4 | diff --git a/ruby/ql/test/library-tests/dataflow/params/TypeTracker.expected b/ruby/ql/test/library-tests/dataflow/params/TypeTracker.expected index d96b678c7870..ff3363a0ea37 100644 --- a/ruby/ql/test/library-tests/dataflow/params/TypeTracker.expected +++ b/ruby/ql/test/library-tests/dataflow/params/TypeTracker.expected @@ -207,7 +207,7 @@ track | params_flow.rb:1:11:1:11 | x | type tracker without call steps | params_flow.rb:137:23:137:31 | call to taint | | params_flow.rb:1:11:1:11 | x | type tracker without call steps | params_flow.rb:137:34:137:42 | call to taint | | params_flow.rb:1:11:1:11 | x | type tracker without call steps with content attribute [] | params_flow.rb:117:1:117:1 | [post] x | -| params_flow.rb:1:11:1:11 | x | type tracker without call steps with content element | params_flow.rb:116:5:116:6 | call to [] | +| params_flow.rb:1:11:1:11 | x | type tracker without call steps with content element | params_flow.rb:117:1:117:1 | [post] x | | params_flow.rb:1:11:1:11 | x | type tracker without call steps with content element | params_flow.rb:118:12:118:13 | * ... | | params_flow.rb:1:11:1:11 | x | type tracker without call steps with content element 0 | params_flow.rb:43:8:43:18 | call to [] | | params_flow.rb:1:11:1:11 | x | type tracker without call steps with content element 0 | params_flow.rb:43:8:43:18 | synthetic splat argument | @@ -2551,7 +2551,7 @@ track | params_flow.rb:117:19:117:27 | call to taint | type tracker with call steps with content splat position 0 | params_flow.rb:11:5:11:11 | synthetic splat argument | | params_flow.rb:117:19:117:27 | call to taint | type tracker without call steps | params_flow.rb:117:19:117:27 | call to taint | | params_flow.rb:117:19:117:27 | call to taint | type tracker without call steps with content attribute [] | params_flow.rb:117:1:117:1 | [post] x | -| params_flow.rb:117:19:117:27 | call to taint | type tracker without call steps with content element | params_flow.rb:116:5:116:6 | call to [] | +| params_flow.rb:117:19:117:27 | call to taint | type tracker without call steps with content element | params_flow.rb:117:1:117:1 | [post] x | | params_flow.rb:117:19:117:27 | call to taint | type tracker without call steps with content element | params_flow.rb:118:12:118:13 | * ... | | params_flow.rb:117:19:117:27 | call to taint | type tracker without call steps with content splat position 1 | params_flow.rb:117:1:117:15 | synthetic splat argument | | params_flow.rb:117:19:117:27 | synthetic splat argument | type tracker with call steps | params_flow.rb:1:1:3:3 | synthetic splat parameter | @@ -2569,7 +2569,7 @@ track | params_flow.rb:117:25:117:26 | 61 | type tracker without call steps | params_flow.rb:117:19:117:27 | call to taint | | params_flow.rb:117:25:117:26 | 61 | type tracker without call steps | params_flow.rb:117:25:117:26 | 61 | | params_flow.rb:117:25:117:26 | 61 | type tracker without call steps with content attribute [] | params_flow.rb:117:1:117:1 | [post] x | -| params_flow.rb:117:25:117:26 | 61 | type tracker without call steps with content element | params_flow.rb:116:5:116:6 | call to [] | +| params_flow.rb:117:25:117:26 | 61 | type tracker without call steps with content element | params_flow.rb:117:1:117:1 | [post] x | | params_flow.rb:117:25:117:26 | 61 | type tracker without call steps with content element | params_flow.rb:118:12:118:13 | * ... | | params_flow.rb:117:25:117:26 | 61 | type tracker without call steps with content splat position 0 | params_flow.rb:117:19:117:27 | synthetic splat argument | | params_flow.rb:117:25:117:26 | 61 | type tracker without call steps with content splat position 1 | params_flow.rb:117:1:117:15 | synthetic splat argument | diff --git a/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected b/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected index ec9c67c2f523..31af9cc7a701 100644 --- a/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected +++ b/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected @@ -163,12 +163,12 @@ track | type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:40:5:40:12 | ...[...] | | type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] | | type_tracker.rb:34:18:34:20 | obj | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] | -| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:38:13:38:25 | call to [] | -| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:50:14:50:26 | call to [] | +| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:39:5:39:9 | [post] array | +| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:51:5:51:10 | [post] array4 | | type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 | type_tracker.rb:35:11:35:15 | call to [] | | type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 | type_tracker.rb:35:11:35:15 | synthetic splat argument | -| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:42:14:42:26 | call to [] | -| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:46:14:46:26 | call to [] | +| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:43:5:43:10 | [post] array2 | +| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content splat position 1 | type_tracker.rb:39:5:39:12 | synthetic splat argument | | type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content splat position 1 | type_tracker.rb:43:5:43:13 | synthetic splat argument | | type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content splat position 1 | type_tracker.rb:47:5:47:13 | synthetic splat argument | @@ -225,32 +225,40 @@ track | type_tracker.rb:42:5:42:10 | array2 | type tracker without call steps | type_tracker.rb:42:5:42:10 | array2 | | type_tracker.rb:42:14:42:26 | Array | type tracker without call steps | type_tracker.rb:42:14:42:26 | Array | | type_tracker.rb:42:14:42:26 | call to [] | type tracker without call steps | type_tracker.rb:42:14:42:26 | call to [] | +| type_tracker.rb:42:14:42:26 | call to [] | type tracker without call steps | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:42:14:42:26 | synthetic splat argument | type tracker without call steps | type_tracker.rb:42:14:42:26 | call to [] | | type_tracker.rb:42:14:42:26 | synthetic splat argument | type tracker without call steps | type_tracker.rb:42:14:42:26 | synthetic splat argument | +| type_tracker.rb:42:14:42:26 | synthetic splat argument | type tracker without call steps | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:42:15:42:15 | 1 | type tracker without call steps | type_tracker.rb:42:15:42:15 | 1 | | type_tracker.rb:42:15:42:15 | 1 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] | | type_tracker.rb:42:15:42:15 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:42:14:42:26 | call to [] | | type_tracker.rb:42:15:42:15 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:42:14:42:26 | synthetic splat argument | +| type_tracker.rb:42:15:42:15 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:42:17:42:17 | 2 | type tracker without call steps | type_tracker.rb:42:17:42:17 | 2 | | type_tracker.rb:42:17:42:17 | 2 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] | | type_tracker.rb:42:17:42:17 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:42:14:42:26 | call to [] | | type_tracker.rb:42:17:42:17 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:42:14:42:26 | synthetic splat argument | +| type_tracker.rb:42:17:42:17 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:42:19:42:19 | 3 | type tracker without call steps | type_tracker.rb:42:19:42:19 | 3 | | type_tracker.rb:42:19:42:19 | 3 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] | | type_tracker.rb:42:19:42:19 | 3 | type tracker without call steps with content element 2 | type_tracker.rb:42:14:42:26 | call to [] | | type_tracker.rb:42:19:42:19 | 3 | type tracker without call steps with content element 2 | type_tracker.rb:42:14:42:26 | synthetic splat argument | +| type_tracker.rb:42:19:42:19 | 3 | type tracker without call steps with content element 2 | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:42:21:42:21 | 4 | type tracker without call steps | type_tracker.rb:42:21:42:21 | 4 | | type_tracker.rb:42:21:42:21 | 4 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] | | type_tracker.rb:42:21:42:21 | 4 | type tracker without call steps with content element 3 | type_tracker.rb:42:14:42:26 | call to [] | | type_tracker.rb:42:21:42:21 | 4 | type tracker without call steps with content element 3 | type_tracker.rb:42:14:42:26 | synthetic splat argument | +| type_tracker.rb:42:21:42:21 | 4 | type tracker without call steps with content element 3 | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:42:23:42:23 | 5 | type tracker without call steps | type_tracker.rb:42:23:42:23 | 5 | | type_tracker.rb:42:23:42:23 | 5 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] | | type_tracker.rb:42:23:42:23 | 5 | type tracker without call steps with content element 4 | type_tracker.rb:42:14:42:26 | call to [] | | type_tracker.rb:42:23:42:23 | 5 | type tracker without call steps with content element 4 | type_tracker.rb:42:14:42:26 | synthetic splat argument | +| type_tracker.rb:42:23:42:23 | 5 | type tracker without call steps with content element 4 | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:42:25:42:25 | 6 | type tracker without call steps | type_tracker.rb:42:25:42:25 | 6 | | type_tracker.rb:42:25:42:25 | 6 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] | | type_tracker.rb:42:25:42:25 | 6 | type tracker without call steps with content element 5 | type_tracker.rb:42:14:42:26 | call to [] | | type_tracker.rb:42:25:42:25 | 6 | type tracker without call steps with content element 5 | type_tracker.rb:42:14:42:26 | synthetic splat argument | +| type_tracker.rb:42:25:42:25 | 6 | type tracker without call steps with content element 5 | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:43:5:43:10 | [post] array2 | type tracker without call steps | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:43:5:43:13 | call to []= | type tracker without call steps | type_tracker.rb:43:5:43:13 | call to []= | | type_tracker.rb:43:5:43:13 | synthetic splat argument | type tracker without call steps | type_tracker.rb:43:5:43:13 | synthetic splat argument | @@ -262,27 +270,35 @@ track | type_tracker.rb:46:5:46:10 | array3 | type tracker without call steps | type_tracker.rb:46:5:46:10 | array3 | | type_tracker.rb:46:14:46:26 | Array | type tracker without call steps | type_tracker.rb:46:14:46:26 | Array | | type_tracker.rb:46:14:46:26 | call to [] | type tracker without call steps | type_tracker.rb:46:14:46:26 | call to [] | +| type_tracker.rb:46:14:46:26 | call to [] | type tracker without call steps | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:46:14:46:26 | synthetic splat argument | type tracker without call steps | type_tracker.rb:46:14:46:26 | call to [] | | type_tracker.rb:46:14:46:26 | synthetic splat argument | type tracker without call steps | type_tracker.rb:46:14:46:26 | synthetic splat argument | +| type_tracker.rb:46:14:46:26 | synthetic splat argument | type tracker without call steps | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:46:15:46:15 | 1 | type tracker without call steps | type_tracker.rb:46:15:46:15 | 1 | | type_tracker.rb:46:15:46:15 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:46:14:46:26 | call to [] | | type_tracker.rb:46:15:46:15 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:46:14:46:26 | synthetic splat argument | +| type_tracker.rb:46:15:46:15 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:46:17:46:17 | 2 | type tracker without call steps | type_tracker.rb:46:17:46:17 | 2 | | type_tracker.rb:46:17:46:17 | 2 | type tracker without call steps | type_tracker.rb:48:5:48:13 | ...[...] | | type_tracker.rb:46:17:46:17 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:46:14:46:26 | call to [] | | type_tracker.rb:46:17:46:17 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:46:14:46:26 | synthetic splat argument | +| type_tracker.rb:46:17:46:17 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:46:19:46:19 | 3 | type tracker without call steps | type_tracker.rb:46:19:46:19 | 3 | | type_tracker.rb:46:19:46:19 | 3 | type tracker without call steps with content element 2 | type_tracker.rb:46:14:46:26 | call to [] | | type_tracker.rb:46:19:46:19 | 3 | type tracker without call steps with content element 2 | type_tracker.rb:46:14:46:26 | synthetic splat argument | +| type_tracker.rb:46:19:46:19 | 3 | type tracker without call steps with content element 2 | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:46:21:46:21 | 4 | type tracker without call steps | type_tracker.rb:46:21:46:21 | 4 | | type_tracker.rb:46:21:46:21 | 4 | type tracker without call steps with content element 3 | type_tracker.rb:46:14:46:26 | call to [] | | type_tracker.rb:46:21:46:21 | 4 | type tracker without call steps with content element 3 | type_tracker.rb:46:14:46:26 | synthetic splat argument | +| type_tracker.rb:46:21:46:21 | 4 | type tracker without call steps with content element 3 | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:46:23:46:23 | 5 | type tracker without call steps | type_tracker.rb:46:23:46:23 | 5 | | type_tracker.rb:46:23:46:23 | 5 | type tracker without call steps with content element 4 | type_tracker.rb:46:14:46:26 | call to [] | | type_tracker.rb:46:23:46:23 | 5 | type tracker without call steps with content element 4 | type_tracker.rb:46:14:46:26 | synthetic splat argument | +| type_tracker.rb:46:23:46:23 | 5 | type tracker without call steps with content element 4 | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:46:25:46:25 | 6 | type tracker without call steps | type_tracker.rb:46:25:46:25 | 6 | | type_tracker.rb:46:25:46:25 | 6 | type tracker without call steps with content element 5 | type_tracker.rb:46:14:46:26 | call to [] | | type_tracker.rb:46:25:46:25 | 6 | type tracker without call steps with content element 5 | type_tracker.rb:46:14:46:26 | synthetic splat argument | +| type_tracker.rb:46:25:46:25 | 6 | type tracker without call steps with content element 5 | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:47:5:47:10 | [post] array3 | type tracker without call steps | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:47:5:47:13 | call to []= | type tracker without call steps | type_tracker.rb:47:5:47:13 | call to []= | | type_tracker.rb:47:5:47:13 | synthetic splat argument | type tracker without call steps | type_tracker.rb:47:5:47:13 | synthetic splat argument | @@ -607,12 +623,14 @@ trackEnd | type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:42:5:42:10 | array2 | | type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:42:5:42:26 | ... = ... | | type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:42:14:42:26 | call to [] | +| type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:43:5:43:10 | array2 | | type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:44:5:44:10 | array2 | | type_tracker.rb:42:14:42:26 | synthetic splat argument | type_tracker.rb:42:5:42:10 | array2 | | type_tracker.rb:42:14:42:26 | synthetic splat argument | type_tracker.rb:42:5:42:26 | ... = ... | | type_tracker.rb:42:14:42:26 | synthetic splat argument | type_tracker.rb:42:14:42:26 | call to [] | | type_tracker.rb:42:14:42:26 | synthetic splat argument | type_tracker.rb:42:14:42:26 | synthetic splat argument | +| type_tracker.rb:42:14:42:26 | synthetic splat argument | type_tracker.rb:43:5:43:10 | [post] array2 | | type_tracker.rb:42:14:42:26 | synthetic splat argument | type_tracker.rb:43:5:43:10 | array2 | | type_tracker.rb:42:14:42:26 | synthetic splat argument | type_tracker.rb:44:5:44:10 | array2 | | type_tracker.rb:42:15:42:15 | 1 | type_tracker.rb:42:15:42:15 | 1 | @@ -640,12 +658,14 @@ trackEnd | type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:46:5:46:10 | array3 | | type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:46:5:46:26 | ... = ... | | type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:46:14:46:26 | call to [] | +| type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:47:5:47:10 | array3 | | type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:48:5:48:10 | array3 | | type_tracker.rb:46:14:46:26 | synthetic splat argument | type_tracker.rb:46:5:46:10 | array3 | | type_tracker.rb:46:14:46:26 | synthetic splat argument | type_tracker.rb:46:5:46:26 | ... = ... | | type_tracker.rb:46:14:46:26 | synthetic splat argument | type_tracker.rb:46:14:46:26 | call to [] | | type_tracker.rb:46:14:46:26 | synthetic splat argument | type_tracker.rb:46:14:46:26 | synthetic splat argument | +| type_tracker.rb:46:14:46:26 | synthetic splat argument | type_tracker.rb:47:5:47:10 | [post] array3 | | type_tracker.rb:46:14:46:26 | synthetic splat argument | type_tracker.rb:47:5:47:10 | array3 | | type_tracker.rb:46:14:46:26 | synthetic splat argument | type_tracker.rb:48:5:48:10 | array3 | | type_tracker.rb:46:15:46:15 | 1 | type_tracker.rb:46:15:46:15 | 1 | From bf3fb685adbaa069f61fa841149ec209a1900186 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 30 Oct 2023 10:52:07 +0100 Subject: [PATCH 2/3] Python: Sync in changes to `SummaryTypeTracker.qll` --- .../new/internal/SummaryTypeTracker.qll | 56 +++++++++++-------- .../new/internal/TypeTrackerSpecific.qll | 5 +- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll b/python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll index 9c6f841651dd..9754838be61e 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll @@ -74,7 +74,7 @@ signature module Input { // Relating nodes to summaries /** Gets a dataflow node respresenting the argument of `call` indicated by `arg`. */ - Node argumentOf(Node call, SummaryComponent arg); + Node argumentOf(Node call, SummaryComponent arg, boolean isOutput); /** Gets a dataflow node respresenting the parameter of `callable` indicated by `param`. */ Node parameterOf(Node callable, SummaryComponent param); @@ -224,11 +224,14 @@ module SummaryFlow implements Output { * as specified by `component`. */ bindingset[call, component] - private I::Node evaluateSummaryComponentLocal(I::Node call, I::SummaryComponent component) { - result = I::argumentOf(call, component) + private I::Node evaluateSummaryComponentLocal( + I::Node call, I::SummaryComponent component, boolean isOutput + ) { + result = I::argumentOf(call, component, isOutput) or component = I::return() and - result = call + result = call and + isOutput = true } /** @@ -280,27 +283,34 @@ module SummaryFlow implements Output { */ pragma[nomagic] private I::Node evaluateSummaryComponentStackLocal( - I::SummarizedCallable callable, I::Node call, I::SummaryComponentStack stack + I::SummarizedCallable callable, I::Node call, I::SummaryComponentStack stack, boolean isOutput ) { exists(I::SummaryComponent component | dependsOnSummaryComponentStackLeaf(callable, component) and stack = I::singleton(component) and call = I::callTo(callable) and - result = evaluateSummaryComponentLocal(call, component) + result = evaluateSummaryComponentLocal(call, component, isOutput) ) or - exists(I::Node prev, I::SummaryComponent head, I::SummaryComponentStack tail | - prev = evaluateSummaryComponentStackLocal(callable, call, tail) and + exists( + I::Node prev, I::SummaryComponent head, I::SummaryComponentStack tail, boolean isOutput0 + | + prev = evaluateSummaryComponentStackLocal(callable, call, tail, isOutput0) and dependsOnSummaryComponentStackConsLocal(callable, pragma[only_bind_into](head), pragma[only_bind_out](tail)) and stack = I::push(pragma[only_bind_out](head), pragma[only_bind_out](tail)) | - result = I::parameterOf(prev, head) + result = I::parameterOf(prev, head) and + isOutput0 = false and + isOutput = true or - result = I::returnOf(prev, head) + result = I::returnOf(prev, head) and + isOutput0 = false and + isOutput = false or componentLevelStep(head) and - result = prev + result = prev and + isOutput = isOutput0 ) } @@ -312,8 +322,8 @@ module SummaryFlow implements Output { | callable.propagatesFlow(input, output, true) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } @@ -325,8 +335,8 @@ module SummaryFlow implements Output { hasLoadSummary(callable, content, pragma[only_bind_into](input), pragma[only_bind_into](output)) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } @@ -338,8 +348,8 @@ module SummaryFlow implements Output { hasStoreSummary(callable, content, pragma[only_bind_into](input), pragma[only_bind_into](output)) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } @@ -354,8 +364,8 @@ module SummaryFlow implements Output { hasLoadStoreSummary(callable, loadContent, storeContent, pragma[only_bind_into](input), pragma[only_bind_into](output)) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } @@ -369,8 +379,8 @@ module SummaryFlow implements Output { hasWithoutContentSummary(callable, filter, pragma[only_bind_into](input), pragma[only_bind_into](output)) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } @@ -384,8 +394,8 @@ module SummaryFlow implements Output { hasWithContentSummary(callable, filter, pragma[only_bind_into](input), pragma[only_bind_into](output)) and call = I::callTo(callable) and - nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and - nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) + nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input, false) and + nodeTo = evaluateSummaryComponentStackLocal(callable, call, output, true) ) } } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll index bac194aae9e0..beee5674c601 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll @@ -214,10 +214,11 @@ private module SummaryTypeTrackerInput implements SummaryTypeTracker::Input { predicate return = FlowSummary::SummaryComponent::return/0; // Relating nodes to summaries - Node argumentOf(Node call, SummaryComponent arg) { + Node argumentOf(Node call, SummaryComponent arg, boolean isPostUpdate) { exists(DataFlowDispatch::ParameterPosition pos | arg = FlowSummary::SummaryComponent::argument(pos) and - argumentPositionMatch(call, result, pos) + argumentPositionMatch(call, result, pos) and + isPostUpdate = [false, true] // todo: implement when/if Python uses post-update nodes in type tracking ) } From 0c5b528d543dc204c82f2e4a4d980c379773def2 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 1 Nov 2023 08:42:27 +0100 Subject: [PATCH 3/3] Address review comments --- .../new/internal/SummaryTypeTracker.qll | 17 ++++++++++++++--- .../internal/SummaryTypeTracker.qll | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll b/python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll index 9754838be61e..efe7629fffc1 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll @@ -73,8 +73,12 @@ signature module Input { } // Relating nodes to summaries - /** Gets a dataflow node respresenting the argument of `call` indicated by `arg`. */ - Node argumentOf(Node call, SummaryComponent arg, boolean isOutput); + /** + * Gets a dataflow node respresenting the argument of `call` indicated by `arg`. + * + * Returns the post-update node of the argument when `isPostUpdate` is true. + */ + Node argumentOf(Node call, SummaryComponent arg, boolean isPostUpdate); /** Gets a dataflow node respresenting the parameter of `callable` indicated by `param`. */ Node parameterOf(Node callable, SummaryComponent param); @@ -221,7 +225,8 @@ module SummaryFlow implements Output { /** * Gets a data flow `I::Node` corresponding an argument or return value of `call`, - * as specified by `component`. + * as specified by `component`. `isOutput` indicates whether the node represents + * an output node or an input node. */ bindingset[call, component] private I::Node evaluateSummaryComponentLocal( @@ -300,10 +305,16 @@ module SummaryFlow implements Output { pragma[only_bind_out](tail)) and stack = I::push(pragma[only_bind_out](head), pragma[only_bind_out](tail)) | + // `Parameter[X]` is only allowed in the output of flow summaries (hence `isOutput = true`), + // however the target of the parameter (e.g. `Argument[Y].Parameter[X]`) should be fetched + // not from a post-update argument node (hence `isOutput0 = false`) result = I::parameterOf(prev, head) and isOutput0 = false and isOutput = true or + // `ReturnValue` is only allowed in the input of flow summaries (hence `isOutput = false`), + // and the target of the return value (e.g. `Argument[X].ReturnValue`) should be fetched not + // from a post-update argument node (hence `isOutput0 = false`) result = I::returnOf(prev, head) and isOutput0 = false and isOutput = false diff --git a/ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll b/ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll index 9754838be61e..efe7629fffc1 100644 --- a/ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll +++ b/ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll @@ -73,8 +73,12 @@ signature module Input { } // Relating nodes to summaries - /** Gets a dataflow node respresenting the argument of `call` indicated by `arg`. */ - Node argumentOf(Node call, SummaryComponent arg, boolean isOutput); + /** + * Gets a dataflow node respresenting the argument of `call` indicated by `arg`. + * + * Returns the post-update node of the argument when `isPostUpdate` is true. + */ + Node argumentOf(Node call, SummaryComponent arg, boolean isPostUpdate); /** Gets a dataflow node respresenting the parameter of `callable` indicated by `param`. */ Node parameterOf(Node callable, SummaryComponent param); @@ -221,7 +225,8 @@ module SummaryFlow implements Output { /** * Gets a data flow `I::Node` corresponding an argument or return value of `call`, - * as specified by `component`. + * as specified by `component`. `isOutput` indicates whether the node represents + * an output node or an input node. */ bindingset[call, component] private I::Node evaluateSummaryComponentLocal( @@ -300,10 +305,16 @@ module SummaryFlow implements Output { pragma[only_bind_out](tail)) and stack = I::push(pragma[only_bind_out](head), pragma[only_bind_out](tail)) | + // `Parameter[X]` is only allowed in the output of flow summaries (hence `isOutput = true`), + // however the target of the parameter (e.g. `Argument[Y].Parameter[X]`) should be fetched + // not from a post-update argument node (hence `isOutput0 = false`) result = I::parameterOf(prev, head) and isOutput0 = false and isOutput = true or + // `ReturnValue` is only allowed in the input of flow summaries (hence `isOutput = false`), + // and the target of the return value (e.g. `Argument[X].ReturnValue`) should be fetched not + // from a post-update argument node (hence `isOutput0 = false`) result = I::returnOf(prev, head) and isOutput0 = false and isOutput = false