diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 169b6bdd64d..68df2f6f498 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -22,6 +22,22 @@ "command": "${config:python.pythonPath}", }, "problemMatcher": [] + }, + { + "label": "Accept .expected changes from CI", + "type": "process", + // Non-Windows OS will usually have Python 3 already installed at /usr/bin/python3. + "command": "python3", + "args": [ + "misc/scripts/accept-expected-changes-from-ci.py" + ], + "group": "build", + "windows": { + // On Windows, use whatever Python interpreter is configured for this workspace. The default is + // just `python`, so if Python is already on the path, this will find it. + "command": "${config:python.pythonPath}", + }, + "problemMatcher": [] } ] -} \ No newline at end of file +} diff --git a/CODEOWNERS b/CODEOWNERS index 856d325b487..6e2dd9dc66b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -40,3 +40,6 @@ WORKSPACE.bazel @github/codeql-ci-reviewers /.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers /.github/workflows/ruby-* @github/codeql-ruby /.github/workflows/swift.yml @github/codeql-swift + +# Misc +/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll index c2c27158434..8fd43a6ee0c 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll @@ -290,9 +290,9 @@ module ProductFlow { predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn1(node) } } - module Flow1 = DataFlow::GlobalWithState; + private module Flow1 = DataFlow::GlobalWithState; - module Config2 implements DataFlow::StateConfigSig { + private module Config2 implements DataFlow::StateConfigSig { class FlowState = FlowState2; predicate isSource(DataFlow::Node source, FlowState state) { @@ -322,27 +322,90 @@ module ProductFlow { predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn2(node) } } - module Flow2 = DataFlow::GlobalWithState; + private module Flow2 = DataFlow::GlobalWithState; + + private predicate isSourcePair(Flow1::PathNode node1, Flow2::PathNode node2) { + Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState()) + } + + private predicate isSinkPair(Flow1::PathNode node1, Flow2::PathNode node2) { + Config::isSinkPair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState()) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) { + isSourcePair(node1, node2) + or + fwdIsSuccessor(_, _, node1, node2) + } pragma[nomagic] - private predicate reachableInterprocEntry( - Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode node1, Flow2::PathNode node2 + private predicate fwdIsSuccessorExit( + Flow1::PathNode mid1, Flow2::PathNode mid2, Flow1::PathNode succ1, Flow2::PathNode succ2 ) { - Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState()) and - node1 = source1 and - node2 = source2 + isSinkPair(mid1, mid2) and + succ1 = mid1 and + succ2 = mid2 or - exists( - Flow1::PathNode midEntry1, Flow2::PathNode midEntry2, Flow1::PathNode midExit1, - Flow2::PathNode midExit2 - | - reachableInterprocEntry(source1, source2, midEntry1, midEntry2) and - interprocEdgePair(midExit1, midExit2, node1, node2) and - localPathStep1*(midEntry1, midExit1) and - localPathStep2*(midEntry2, midExit2) + interprocEdgePair(mid1, mid2, succ1, succ2) + } + + private predicate fwdIsSuccessor1( + Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2, + Flow1::PathNode succ1, Flow2::PathNode succ2 + ) { + fwdReachableInterprocEntry(pred1, pred2) and + localPathStep1*(pred1, mid1) and + fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2) + } + + private predicate fwdIsSuccessor2( + Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2, + Flow1::PathNode succ1, Flow2::PathNode succ2 + ) { + fwdReachableInterprocEntry(pred1, pred2) and + localPathStep2*(pred2, mid2) and + fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2) + } + + pragma[assume_small_delta] + private predicate fwdIsSuccessor( + Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2 + ) { + exists(Flow1::PathNode mid1, Flow2::PathNode mid2 | + fwdIsSuccessor1(pred1, pred2, mid1, mid2, succ1, succ2) and + fwdIsSuccessor2(pred1, pred2, mid1, mid2, succ1, succ2) ) } + pragma[assume_small_delta] + pragma[nomagic] + private predicate revReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) { + fwdReachableInterprocEntry(node1, node2) and + isSinkPair(node1, node2) + or + exists(Flow1::PathNode succ1, Flow2::PathNode succ2 | + revReachableInterprocEntry(succ1, succ2) and + fwdIsSuccessor(node1, node2, succ1, succ2) + ) + } + + private newtype TNodePair = + TMkNodePair(Flow1::PathNode node1, Flow2::PathNode node2) { + revReachableInterprocEntry(node1, node2) + } + + private predicate pathSucc(TNodePair n1, TNodePair n2) { + exists(Flow1::PathNode n11, Flow2::PathNode n12, Flow1::PathNode n21, Flow2::PathNode n22 | + n1 = TMkNodePair(n11, n12) and + n2 = TMkNodePair(n21, n22) and + fwdIsSuccessor(n11, n12, n21, n22) + ) + } + + private predicate pathSuccPlus(TNodePair n1, TNodePair n2) = fastTC(pathSucc/2)(n1, n2) + private predicate localPathStep1(Flow1::PathNode pred, Flow1::PathNode succ) { Flow1::PathGraph::edges(pred, succ) and pragma[only_bind_out](pred.getNode().getEnclosingCallable()) = @@ -474,11 +537,14 @@ module ProductFlow { private predicate reachable( Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode sink1, Flow2::PathNode sink2 ) { - exists(Flow1::PathNode mid1, Flow2::PathNode mid2 | - reachableInterprocEntry(source1, source2, mid1, mid2) and - Config::isSinkPair(sink1.getNode(), sink1.getState(), sink2.getNode(), sink2.getState()) and - localPathStep1*(mid1, sink1) and - localPathStep2*(mid2, sink2) + isSourcePair(source1, source2) and + isSinkPair(sink1, sink2) and + exists(TNodePair n1, TNodePair n2 | + n1 = TMkNodePair(source1, source2) and + n2 = TMkNodePair(sink1, sink2) + | + pathSuccPlus(n1, n2) or + n1 = n2 ) } } diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql index 79a5497f46d..39f91389ab9 100644 --- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql +++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql @@ -78,6 +78,149 @@ predicate isSinkPairImpl( ) } +module ValidState { + /** + * In the `StringSizeConfig` configuration we use an integer as the flow state for the second + * projection of the dataflow graph. The integer represents an offset that is added to the + * size of the allocation. For example, given: + * ```cpp + * char* p = new char[size + 1]; + * size += 1; + * memset(p, 0, size); + * ``` + * the initial flow state is `1`. This represents the fact that `size + 1` is a valid bound + * for the size of the allocation pointed to by `p`. After updating the size using `+=`, the + * flow state changes to `0`, which represents the fact that `size + 0` is a valid bound for + * the allocation. + * + * So we need to compute a set of valid integers that represent the offset applied to the + * size. We do this in two steps: + * 1. We first perform the dataflow traversal that the second projection of the product-flow + * library will perform, and visit all the places where the size argument is modified. + * 2. Once that dataflow traversal is done, we accumulate the offsets added at each places + * where the offset is modified (see `validStateImpl`). + * + * Because we want to guarantee that each place where we modify the offset has a `PathNode` + * we "flip" a boolean flow state in each `isAdditionalFlowStep`. This ensures that the node + * has a corresponding `PathNode`. + */ + private module ValidStateConfig implements DataFlow::StateConfigSig { + class FlowState = boolean; + + predicate isSource(DataFlow::Node source, FlowState state) { + hasSize(_, source, _) and + state = false + } + + predicate isSink(DataFlow::Node sink, FlowState state) { + isSinkPairImpl(_, _, sink, _, _) and + state = [false, true] + } + + predicate isBarrier(DataFlow::Node node, FlowState state) { none() } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + exists(AddInstruction add, Operand op, int delta | + add.hasOperands(node1.asOperand(), op) and + semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and + node2.asInstruction() = add and + state1 = [false, true] and + state2 = state1.booleanNot() + ) + } + + predicate includeHiddenNodes() { any() } + } + + private import DataFlow::GlobalWithState + + private predicate inLoop(PathNode n) { n.getASuccessor+() = n } + + /** + * Holds if `value` is a possible offset for `n`. + * + * To ensure termination, we limit `value` to be in the + * range `[-2, 2]` if the node is part of a loop. Without + * this restriction we wouldn't terminate on an example like: + * ```cpp + * while(unknown()) { size++; } + * ``` + */ + private predicate validStateImpl(PathNode n, int value) { + // If the dataflow node depends recursively on itself we restrict the range. + (inLoop(n) implies value = [-2 .. 2]) and + ( + // For the dataflow source we have an allocation such as `malloc(size + k)`, + // and the value of the flow-state is then `k`. + hasSize(_, n.getNode(), value) + or + // For a dataflow sink any `value` that is strictly smaller than the delta + // needs to be a valid flow-state. That is, for a snippet like: + // ``` + // p = b ? new char[size] : new char[size + 1]; + // memset(p, 0, size + 2); + // ``` + // the valid flow-states at the `memset` must include the set `{0, 1}` since the + // flow-state at `new char[size]` is `0`, and the flow-state at `new char[size + 1]` + // is `1`. + // + // So we find a valid flow-state at the sink's predecessor, and use the definition + // of our sink predicate to compute the valid flow-states at the sink. + exists(int delta, PathNode n0 | + n0.getASuccessor() = n and + validStateImpl(n0, value) and + isSinkPairImpl(_, _, n.getNode(), delta, _) and + delta > value + ) + or + // For a non-source and non-sink node there is two cases to consider. + // 1. A node where we have to update the flow-state, or + // 2. A node that doesn't update the flow-state. + // + // For case 1, we compute the new flow-state by adding the constant operand of the + // `AddInstruction` to the flow-state of any predecessor node. + // For case 2 we simply propagate the valid flow-states from the predecessor node to + // the next one. + exists(PathNode n0, DataFlow::Node node0, DataFlow::Node node, int value0 | + n0.getASuccessor() = n and + validStateImpl(n0, value0) and + node = n.getNode() and + node0 = n0.getNode() + | + exists(int delta | + isAdditionalFlowStep2(node0, node, delta) and + value0 = value + delta + ) + or + not isAdditionalFlowStep2(node0, node, _) and + value = value0 + ) + ) + } + + predicate validState(DataFlow::Node n, int value) { + validStateImpl(any(PathNode pn | pn.getNode() = n), value) + } +} + +import ValidState + +/** + * Holds if `node2` is a dataflow node that represents an addition of two operands `op1` + * and `op2` such that: + * 1. `node1` is the dataflow node that represents `op1`, and + * 2. the value of `op2` can be upper bounded by `delta.` + */ +predicate isAdditionalFlowStep2(DataFlow::Node node1, DataFlow::Node node2, int delta) { + exists(AddInstruction add, Operand op | + add.hasOperands(node1.asOperand(), op) and + semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and + node2.asInstruction() = add + ) +} + module StringSizeConfig implements ProductFlow::StateConfigSig { class FlowState1 = Unit; @@ -100,7 +243,7 @@ module StringSizeConfig implements ProductFlow::StateConfigSig { DataFlow::Node bufSink, FlowState1 state1, DataFlow::Node sizeSink, FlowState2 state2 ) { exists(state1) and - state2 = [-32 .. 32] and // An arbitrary bound because we need to bound `state2` + validState(sizeSink, state2) and exists(int delta | isSinkPairImpl(_, bufSink, sizeSink, delta, _) and delta > state2 @@ -111,6 +254,10 @@ module StringSizeConfig implements ProductFlow::StateConfigSig { predicate isBarrier2(DataFlow::Node node, FlowState2 state) { none() } + predicate isBarrierOut2(DataFlow::Node node) { + node = any(DataFlow::SsaPhiNode phi).getAnInput(true) + } + predicate isAdditionalFlowStep1( DataFlow::Node node1, FlowState1 state1, DataFlow::Node node2, FlowState1 state2 ) { @@ -120,14 +267,10 @@ module StringSizeConfig implements ProductFlow::StateConfigSig { predicate isAdditionalFlowStep2( DataFlow::Node node1, FlowState2 state1, DataFlow::Node node2, FlowState2 state2 ) { - exists(AddInstruction add, Operand op, int delta, int s1, int s2 | - s1 = [-32 .. 32] and // An arbitrary bound because we need to bound `state` - state1 = s1 and - state2 = s2 and - add.hasOperands(node1.asOperand(), op) and - semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and - node2.asInstruction() = add and - s1 = s2 + delta + validState(node2, state2) and + exists(int delta | + isAdditionalFlowStep2(node1, node2, delta) and + state1 = state2 + delta ) } } diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql index a42249aeafa..f5403ad4c03 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql @@ -324,6 +324,16 @@ query predicate edges(MergedPathNode node1, MergedPathNode node2) { joinOn2(node1.asPathNode3(), node2.asSinkNode(), _) } +query predicate subpaths( + MergedPathNode arg, MergedPathNode par, MergedPathNode ret, MergedPathNode out +) { + AllocToInvalidPointerFlow::PathGraph1::subpaths(arg.asPathNode1(), par.asPathNode1(), + ret.asPathNode1(), out.asPathNode1()) + or + InvalidPointerToDerefFlow::PathGraph::subpaths(arg.asPathNode3(), par.asPathNode3(), + ret.asPathNode3(), out.asPathNode3()) +} + /** * Holds if `p1` is a sink of `AllocToInvalidPointerConf` and `p2` is a source * of `InvalidPointerToDerefConf`, and they are connected through `pai`. diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected index 3b450ac9b8f..f0fb883bffd 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected @@ -1,202 +1,62 @@ edges -| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | -| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | | test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | | test.cpp:18:5:18:30 | ... = ... | test.cpp:18:10:18:15 | str indirection [post update] [string] | | test.cpp:18:10:18:15 | str indirection [post update] [string] | test.cpp:16:11:16:21 | mk_string_t indirection [string] | | test.cpp:18:19:18:24 | call to malloc | test.cpp:18:5:18:30 | ... = ... | -| test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | test.cpp:26:13:26:15 | str indirection [string] | -| test.cpp:26:13:26:15 | str indirection [string] | test.cpp:26:18:26:23 | string | -| test.cpp:26:13:26:15 | str indirection [string] | test.cpp:26:18:26:23 | string indirection | -| test.cpp:26:18:26:23 | string indirection | test.cpp:26:18:26:23 | string | -| test.cpp:29:32:29:34 | str indirection [string] | test.cpp:30:13:30:15 | str indirection [string] | -| test.cpp:30:13:30:15 | str indirection [string] | test.cpp:30:18:30:23 | string | -| test.cpp:30:13:30:15 | str indirection [string] | test.cpp:30:18:30:23 | string indirection | -| test.cpp:30:18:30:23 | string indirection | test.cpp:30:18:30:23 | string | -| test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | test.cpp:35:21:35:23 | str indirection [string] | -| test.cpp:35:21:35:23 | str indirection [string] | test.cpp:29:32:29:34 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:41:13:41:15 | str indirection [string] | | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:42:13:42:15 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:44:13:44:15 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:45:13:45:15 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:48:17:48:19 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:52:17:52:19 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:56:17:56:19 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:60:17:60:19 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:64:17:64:19 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:68:17:68:19 | str indirection [string] | | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:72:17:72:19 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:76:17:76:19 | str indirection [string] | | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:80:17:80:19 | str indirection [string] | -| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:84:17:84:19 | str indirection [string] | -| test.cpp:41:13:41:15 | str indirection [string] | test.cpp:41:18:41:23 | string | -| test.cpp:41:13:41:15 | str indirection [string] | test.cpp:41:18:41:23 | string indirection | -| test.cpp:41:18:41:23 | string indirection | test.cpp:41:18:41:23 | string | | test.cpp:42:13:42:15 | str indirection [string] | test.cpp:42:18:42:23 | string | | test.cpp:42:13:42:15 | str indirection [string] | test.cpp:42:18:42:23 | string indirection | | test.cpp:42:18:42:23 | string indirection | test.cpp:42:18:42:23 | string | -| test.cpp:44:13:44:15 | str indirection [string] | test.cpp:44:18:44:23 | string | -| test.cpp:44:13:44:15 | str indirection [string] | test.cpp:44:18:44:23 | string indirection | -| test.cpp:44:18:44:23 | string indirection | test.cpp:44:18:44:23 | string | -| test.cpp:45:13:45:15 | str indirection [string] | test.cpp:45:18:45:23 | string | -| test.cpp:45:13:45:15 | str indirection [string] | test.cpp:45:18:45:23 | string indirection | -| test.cpp:45:18:45:23 | string indirection | test.cpp:45:18:45:23 | string | -| test.cpp:48:17:48:19 | str indirection [string] | test.cpp:48:22:48:27 | string | -| test.cpp:48:17:48:19 | str indirection [string] | test.cpp:48:22:48:27 | string indirection | -| test.cpp:48:22:48:27 | string indirection | test.cpp:48:22:48:27 | string | -| test.cpp:52:17:52:19 | str indirection [string] | test.cpp:52:22:52:27 | string | -| test.cpp:52:17:52:19 | str indirection [string] | test.cpp:52:22:52:27 | string indirection | -| test.cpp:52:22:52:27 | string indirection | test.cpp:52:22:52:27 | string | -| test.cpp:56:17:56:19 | str indirection [string] | test.cpp:56:22:56:27 | string | -| test.cpp:56:17:56:19 | str indirection [string] | test.cpp:56:22:56:27 | string indirection | -| test.cpp:56:22:56:27 | string indirection | test.cpp:56:22:56:27 | string | -| test.cpp:60:17:60:19 | str indirection [string] | test.cpp:60:22:60:27 | string | -| test.cpp:60:17:60:19 | str indirection [string] | test.cpp:60:22:60:27 | string indirection | -| test.cpp:60:22:60:27 | string indirection | test.cpp:60:22:60:27 | string | -| test.cpp:64:17:64:19 | str indirection [string] | test.cpp:64:22:64:27 | string | -| test.cpp:64:17:64:19 | str indirection [string] | test.cpp:64:22:64:27 | string indirection | -| test.cpp:64:22:64:27 | string indirection | test.cpp:64:22:64:27 | string | -| test.cpp:68:17:68:19 | str indirection [string] | test.cpp:68:22:68:27 | string | -| test.cpp:68:17:68:19 | str indirection [string] | test.cpp:68:22:68:27 | string indirection | -| test.cpp:68:22:68:27 | string indirection | test.cpp:68:22:68:27 | string | | test.cpp:72:17:72:19 | str indirection [string] | test.cpp:72:22:72:27 | string | | test.cpp:72:17:72:19 | str indirection [string] | test.cpp:72:22:72:27 | string indirection | | test.cpp:72:22:72:27 | string indirection | test.cpp:72:22:72:27 | string | -| test.cpp:76:17:76:19 | str indirection [string] | test.cpp:76:22:76:27 | string | -| test.cpp:76:17:76:19 | str indirection [string] | test.cpp:76:22:76:27 | string indirection | -| test.cpp:76:22:76:27 | string indirection | test.cpp:76:22:76:27 | string | | test.cpp:80:17:80:19 | str indirection [string] | test.cpp:80:22:80:27 | string | | test.cpp:80:17:80:19 | str indirection [string] | test.cpp:80:22:80:27 | string indirection | | test.cpp:80:22:80:27 | string indirection | test.cpp:80:22:80:27 | string | -| test.cpp:84:17:84:19 | str indirection [string] | test.cpp:84:22:84:27 | string | -| test.cpp:84:17:84:19 | str indirection [string] | test.cpp:84:22:84:27 | string indirection | -| test.cpp:84:22:84:27 | string indirection | test.cpp:84:22:84:27 | string | | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | | test.cpp:90:5:90:34 | ... = ... | test.cpp:90:10:90:15 | str indirection [post update] [string] | | test.cpp:90:10:90:15 | str indirection [post update] [string] | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | | test.cpp:90:19:90:24 | call to malloc | test.cpp:90:5:90:34 | ... = ... | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:98:13:98:15 | str indirection [string] | | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:99:13:99:15 | str indirection [string] | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:101:13:101:15 | str indirection [string] | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:102:13:102:15 | str indirection [string] | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:105:17:105:19 | str indirection [string] | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:109:17:109:19 | str indirection [string] | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:113:17:113:19 | str indirection [string] | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:117:17:117:19 | str indirection [string] | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:121:17:121:19 | str indirection [string] | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:125:17:125:19 | str indirection [string] | | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:129:17:129:19 | str indirection [string] | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:133:17:133:19 | str indirection [string] | | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:137:17:137:19 | str indirection [string] | -| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:141:17:141:19 | str indirection [string] | -| test.cpp:98:13:98:15 | str indirection [string] | test.cpp:98:18:98:23 | string | -| test.cpp:98:13:98:15 | str indirection [string] | test.cpp:98:18:98:23 | string indirection | -| test.cpp:98:18:98:23 | string indirection | test.cpp:98:18:98:23 | string | | test.cpp:99:13:99:15 | str indirection [string] | test.cpp:99:18:99:23 | string | | test.cpp:99:13:99:15 | str indirection [string] | test.cpp:99:18:99:23 | string indirection | | test.cpp:99:18:99:23 | string indirection | test.cpp:99:18:99:23 | string | -| test.cpp:101:13:101:15 | str indirection [string] | test.cpp:101:18:101:23 | string | -| test.cpp:101:13:101:15 | str indirection [string] | test.cpp:101:18:101:23 | string indirection | -| test.cpp:101:18:101:23 | string indirection | test.cpp:101:18:101:23 | string | -| test.cpp:102:13:102:15 | str indirection [string] | test.cpp:102:18:102:23 | string | -| test.cpp:102:13:102:15 | str indirection [string] | test.cpp:102:18:102:23 | string indirection | -| test.cpp:102:18:102:23 | string indirection | test.cpp:102:18:102:23 | string | -| test.cpp:105:17:105:19 | str indirection [string] | test.cpp:105:22:105:27 | string | -| test.cpp:105:17:105:19 | str indirection [string] | test.cpp:105:22:105:27 | string indirection | -| test.cpp:105:22:105:27 | string indirection | test.cpp:105:22:105:27 | string | -| test.cpp:109:17:109:19 | str indirection [string] | test.cpp:109:22:109:27 | string | -| test.cpp:109:17:109:19 | str indirection [string] | test.cpp:109:22:109:27 | string indirection | -| test.cpp:109:22:109:27 | string indirection | test.cpp:109:22:109:27 | string | -| test.cpp:113:17:113:19 | str indirection [string] | test.cpp:113:22:113:27 | string | -| test.cpp:113:17:113:19 | str indirection [string] | test.cpp:113:22:113:27 | string indirection | -| test.cpp:113:22:113:27 | string indirection | test.cpp:113:22:113:27 | string | -| test.cpp:117:17:117:19 | str indirection [string] | test.cpp:117:22:117:27 | string | -| test.cpp:117:17:117:19 | str indirection [string] | test.cpp:117:22:117:27 | string indirection | -| test.cpp:117:22:117:27 | string indirection | test.cpp:117:22:117:27 | string | -| test.cpp:121:17:121:19 | str indirection [string] | test.cpp:121:22:121:27 | string | -| test.cpp:121:17:121:19 | str indirection [string] | test.cpp:121:22:121:27 | string indirection | -| test.cpp:121:22:121:27 | string indirection | test.cpp:121:22:121:27 | string | -| test.cpp:125:17:125:19 | str indirection [string] | test.cpp:125:22:125:27 | string | -| test.cpp:125:17:125:19 | str indirection [string] | test.cpp:125:22:125:27 | string indirection | -| test.cpp:125:22:125:27 | string indirection | test.cpp:125:22:125:27 | string | | test.cpp:129:17:129:19 | str indirection [string] | test.cpp:129:22:129:27 | string | | test.cpp:129:17:129:19 | str indirection [string] | test.cpp:129:22:129:27 | string indirection | | test.cpp:129:22:129:27 | string indirection | test.cpp:129:22:129:27 | string | -| test.cpp:133:17:133:19 | str indirection [string] | test.cpp:133:22:133:27 | string | -| test.cpp:133:17:133:19 | str indirection [string] | test.cpp:133:22:133:27 | string indirection | -| test.cpp:133:22:133:27 | string indirection | test.cpp:133:22:133:27 | string | | test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string | | test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string indirection | | test.cpp:137:22:137:27 | string indirection | test.cpp:137:22:137:27 | string | -| test.cpp:141:17:141:19 | str indirection [string] | test.cpp:141:22:141:27 | string | -| test.cpp:141:17:141:19 | str indirection [string] | test.cpp:141:22:141:27 | string indirection | -| test.cpp:141:22:141:27 | string indirection | test.cpp:141:22:141:27 | string | | test.cpp:147:5:147:34 | ... = ... | test.cpp:147:10:147:15 | str indirection [post update] [string] | -| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:150:13:150:15 | str indirection [string] | -| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:151:13:151:15 | str indirection [string] | | test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:152:13:152:15 | str indirection [string] | | test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:154:13:154:15 | str indirection [string] | -| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:155:13:155:15 | str indirection [string] | | test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:156:13:156:15 | str indirection [string] | -| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:159:17:159:19 | str indirection [string] | -| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:163:17:163:19 | str indirection [string] | -| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:167:17:167:19 | str indirection [string] | -| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:171:17:171:19 | str indirection [string] | | test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:175:17:175:19 | str indirection [string] | -| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:179:17:179:19 | str indirection [string] | -| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:183:17:183:19 | str indirection [string] | | test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:187:17:187:19 | str indirection [string] | -| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:191:17:191:19 | str indirection [string] | | test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:195:17:195:19 | str indirection [string] | | test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:199:17:199:19 | str indirection [string] | | test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:203:17:203:19 | str indirection [string] | | test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:207:17:207:19 | str indirection [string] | | test.cpp:147:19:147:24 | call to malloc | test.cpp:147:5:147:34 | ... = ... | -| test.cpp:150:13:150:15 | str indirection [string] | test.cpp:150:18:150:23 | string | -| test.cpp:150:13:150:15 | str indirection [string] | test.cpp:150:18:150:23 | string indirection | -| test.cpp:150:18:150:23 | string indirection | test.cpp:150:18:150:23 | string | -| test.cpp:151:13:151:15 | str indirection [string] | test.cpp:151:18:151:23 | string | -| test.cpp:151:13:151:15 | str indirection [string] | test.cpp:151:18:151:23 | string indirection | -| test.cpp:151:18:151:23 | string indirection | test.cpp:151:18:151:23 | string | | test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string | | test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string indirection | | test.cpp:152:18:152:23 | string indirection | test.cpp:152:18:152:23 | string | | test.cpp:154:13:154:15 | str indirection [string] | test.cpp:154:18:154:23 | string | | test.cpp:154:13:154:15 | str indirection [string] | test.cpp:154:18:154:23 | string indirection | | test.cpp:154:18:154:23 | string indirection | test.cpp:154:18:154:23 | string | -| test.cpp:155:13:155:15 | str indirection [string] | test.cpp:155:18:155:23 | string | -| test.cpp:155:13:155:15 | str indirection [string] | test.cpp:155:18:155:23 | string indirection | -| test.cpp:155:18:155:23 | string indirection | test.cpp:155:18:155:23 | string | | test.cpp:156:13:156:15 | str indirection [string] | test.cpp:156:18:156:23 | string | | test.cpp:156:13:156:15 | str indirection [string] | test.cpp:156:18:156:23 | string indirection | | test.cpp:156:18:156:23 | string indirection | test.cpp:156:18:156:23 | string | -| test.cpp:159:17:159:19 | str indirection [string] | test.cpp:159:22:159:27 | string | -| test.cpp:159:17:159:19 | str indirection [string] | test.cpp:159:22:159:27 | string indirection | -| test.cpp:159:22:159:27 | string indirection | test.cpp:159:22:159:27 | string | -| test.cpp:163:17:163:19 | str indirection [string] | test.cpp:163:22:163:27 | string | -| test.cpp:163:17:163:19 | str indirection [string] | test.cpp:163:22:163:27 | string indirection | -| test.cpp:163:22:163:27 | string indirection | test.cpp:163:22:163:27 | string | -| test.cpp:167:17:167:19 | str indirection [string] | test.cpp:167:22:167:27 | string | -| test.cpp:167:17:167:19 | str indirection [string] | test.cpp:167:22:167:27 | string indirection | -| test.cpp:167:22:167:27 | string indirection | test.cpp:167:22:167:27 | string | -| test.cpp:171:17:171:19 | str indirection [string] | test.cpp:171:22:171:27 | string | -| test.cpp:171:17:171:19 | str indirection [string] | test.cpp:171:22:171:27 | string indirection | -| test.cpp:171:22:171:27 | string indirection | test.cpp:171:22:171:27 | string | | test.cpp:175:17:175:19 | str indirection [string] | test.cpp:175:22:175:27 | string | | test.cpp:175:17:175:19 | str indirection [string] | test.cpp:175:22:175:27 | string indirection | | test.cpp:175:22:175:27 | string indirection | test.cpp:175:22:175:27 | string | -| test.cpp:179:17:179:19 | str indirection [string] | test.cpp:179:22:179:27 | string | -| test.cpp:179:17:179:19 | str indirection [string] | test.cpp:179:22:179:27 | string indirection | -| test.cpp:179:22:179:27 | string indirection | test.cpp:179:22:179:27 | string | -| test.cpp:183:17:183:19 | str indirection [string] | test.cpp:183:22:183:27 | string | -| test.cpp:183:17:183:19 | str indirection [string] | test.cpp:183:22:183:27 | string indirection | -| test.cpp:183:22:183:27 | string indirection | test.cpp:183:22:183:27 | string | | test.cpp:187:17:187:19 | str indirection [string] | test.cpp:187:22:187:27 | string | | test.cpp:187:17:187:19 | str indirection [string] | test.cpp:187:22:187:27 | string indirection | | test.cpp:187:22:187:27 | string indirection | test.cpp:187:22:187:27 | string | -| test.cpp:191:17:191:19 | str indirection [string] | test.cpp:191:22:191:27 | string | -| test.cpp:191:17:191:19 | str indirection [string] | test.cpp:191:22:191:27 | string indirection | -| test.cpp:191:22:191:27 | string indirection | test.cpp:191:22:191:27 | string | | test.cpp:195:17:195:19 | str indirection [string] | test.cpp:195:22:195:27 | string | | test.cpp:195:17:195:19 | str indirection [string] | test.cpp:195:22:195:27 | string indirection | | test.cpp:195:22:195:27 | string indirection | test.cpp:195:22:195:27 | string | @@ -223,159 +83,54 @@ edges | test.cpp:243:12:243:14 | str indirection [string] | test.cpp:243:16:243:21 | string indirection | | test.cpp:243:16:243:21 | string indirection | test.cpp:243:12:243:21 | string | | test.cpp:249:20:249:27 | call to my_alloc | test.cpp:250:12:250:12 | p | +| test.cpp:256:17:256:22 | call to malloc | test.cpp:257:12:257:12 | p | nodes | test.cpp:16:11:16:21 | mk_string_t indirection [string] | semmle.label | mk_string_t indirection [string] | | test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... | | test.cpp:18:10:18:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] | | test.cpp:18:19:18:24 | call to malloc | semmle.label | call to malloc | -| test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] | -| test.cpp:26:13:26:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:26:18:26:23 | string | semmle.label | string | -| test.cpp:26:18:26:23 | string indirection | semmle.label | string indirection | -| test.cpp:29:32:29:34 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:30:13:30:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:30:18:30:23 | string | semmle.label | string | -| test.cpp:30:18:30:23 | string indirection | semmle.label | string indirection | -| test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] | -| test.cpp:35:21:35:23 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] | -| test.cpp:41:13:41:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:41:18:41:23 | string | semmle.label | string | -| test.cpp:41:18:41:23 | string indirection | semmle.label | string indirection | | test.cpp:42:13:42:15 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:42:18:42:23 | string | semmle.label | string | | test.cpp:42:18:42:23 | string indirection | semmle.label | string indirection | -| test.cpp:44:13:44:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:44:18:44:23 | string | semmle.label | string | -| test.cpp:44:18:44:23 | string indirection | semmle.label | string indirection | -| test.cpp:45:13:45:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:45:18:45:23 | string | semmle.label | string | -| test.cpp:45:18:45:23 | string indirection | semmle.label | string indirection | -| test.cpp:48:17:48:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:48:22:48:27 | string | semmle.label | string | -| test.cpp:48:22:48:27 | string indirection | semmle.label | string indirection | -| test.cpp:52:17:52:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:52:22:52:27 | string | semmle.label | string | -| test.cpp:52:22:52:27 | string indirection | semmle.label | string indirection | -| test.cpp:56:17:56:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:56:22:56:27 | string | semmle.label | string | -| test.cpp:56:22:56:27 | string indirection | semmle.label | string indirection | -| test.cpp:60:17:60:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:60:22:60:27 | string | semmle.label | string | -| test.cpp:60:22:60:27 | string indirection | semmle.label | string indirection | -| test.cpp:64:17:64:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:64:22:64:27 | string | semmle.label | string | -| test.cpp:64:22:64:27 | string indirection | semmle.label | string indirection | -| test.cpp:68:17:68:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:68:22:68:27 | string | semmle.label | string | -| test.cpp:68:22:68:27 | string indirection | semmle.label | string indirection | | test.cpp:72:17:72:19 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:72:22:72:27 | string | semmle.label | string | | test.cpp:72:22:72:27 | string indirection | semmle.label | string indirection | -| test.cpp:76:17:76:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:76:22:76:27 | string | semmle.label | string | -| test.cpp:76:22:76:27 | string indirection | semmle.label | string indirection | | test.cpp:80:17:80:19 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:80:22:80:27 | string | semmle.label | string | | test.cpp:80:22:80:27 | string indirection | semmle.label | string indirection | -| test.cpp:84:17:84:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:84:22:84:27 | string | semmle.label | string | -| test.cpp:84:22:84:27 | string indirection | semmle.label | string indirection | | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | semmle.label | mk_string_t_plus_one indirection [string] | | test.cpp:90:5:90:34 | ... = ... | semmle.label | ... = ... | | test.cpp:90:10:90:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] | | test.cpp:90:19:90:24 | call to malloc | semmle.label | call to malloc | | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | semmle.label | call to mk_string_t_plus_one indirection [string] | -| test.cpp:98:13:98:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:98:18:98:23 | string | semmle.label | string | -| test.cpp:98:18:98:23 | string indirection | semmle.label | string indirection | | test.cpp:99:13:99:15 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:99:18:99:23 | string | semmle.label | string | | test.cpp:99:18:99:23 | string indirection | semmle.label | string indirection | -| test.cpp:101:13:101:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:101:18:101:23 | string | semmle.label | string | -| test.cpp:101:18:101:23 | string indirection | semmle.label | string indirection | -| test.cpp:102:13:102:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:102:18:102:23 | string | semmle.label | string | -| test.cpp:102:18:102:23 | string indirection | semmle.label | string indirection | -| test.cpp:105:17:105:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:105:22:105:27 | string | semmle.label | string | -| test.cpp:105:22:105:27 | string indirection | semmle.label | string indirection | -| test.cpp:109:17:109:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:109:22:109:27 | string | semmle.label | string | -| test.cpp:109:22:109:27 | string indirection | semmle.label | string indirection | -| test.cpp:113:17:113:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:113:22:113:27 | string | semmle.label | string | -| test.cpp:113:22:113:27 | string indirection | semmle.label | string indirection | -| test.cpp:117:17:117:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:117:22:117:27 | string | semmle.label | string | -| test.cpp:117:22:117:27 | string indirection | semmle.label | string indirection | -| test.cpp:121:17:121:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:121:22:121:27 | string | semmle.label | string | -| test.cpp:121:22:121:27 | string indirection | semmle.label | string indirection | -| test.cpp:125:17:125:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:125:22:125:27 | string | semmle.label | string | -| test.cpp:125:22:125:27 | string indirection | semmle.label | string indirection | | test.cpp:129:17:129:19 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:129:22:129:27 | string | semmle.label | string | | test.cpp:129:22:129:27 | string indirection | semmle.label | string indirection | -| test.cpp:133:17:133:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:133:22:133:27 | string | semmle.label | string | -| test.cpp:133:22:133:27 | string indirection | semmle.label | string indirection | | test.cpp:137:17:137:19 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:137:22:137:27 | string | semmle.label | string | | test.cpp:137:22:137:27 | string indirection | semmle.label | string indirection | -| test.cpp:141:17:141:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:141:22:141:27 | string | semmle.label | string | -| test.cpp:141:22:141:27 | string indirection | semmle.label | string indirection | | test.cpp:147:5:147:34 | ... = ... | semmle.label | ... = ... | | test.cpp:147:10:147:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] | | test.cpp:147:19:147:24 | call to malloc | semmle.label | call to malloc | -| test.cpp:150:13:150:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:150:18:150:23 | string | semmle.label | string | -| test.cpp:150:18:150:23 | string indirection | semmle.label | string indirection | -| test.cpp:151:13:151:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:151:18:151:23 | string | semmle.label | string | -| test.cpp:151:18:151:23 | string indirection | semmle.label | string indirection | | test.cpp:152:13:152:15 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:152:18:152:23 | string | semmle.label | string | | test.cpp:152:18:152:23 | string indirection | semmle.label | string indirection | | test.cpp:154:13:154:15 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:154:18:154:23 | string | semmle.label | string | | test.cpp:154:18:154:23 | string indirection | semmle.label | string indirection | -| test.cpp:155:13:155:15 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:155:18:155:23 | string | semmle.label | string | -| test.cpp:155:18:155:23 | string indirection | semmle.label | string indirection | | test.cpp:156:13:156:15 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:156:18:156:23 | string | semmle.label | string | | test.cpp:156:18:156:23 | string indirection | semmle.label | string indirection | -| test.cpp:159:17:159:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:159:22:159:27 | string | semmle.label | string | -| test.cpp:159:22:159:27 | string indirection | semmle.label | string indirection | -| test.cpp:163:17:163:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:163:22:163:27 | string | semmle.label | string | -| test.cpp:163:22:163:27 | string indirection | semmle.label | string indirection | -| test.cpp:167:17:167:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:167:22:167:27 | string | semmle.label | string | -| test.cpp:167:22:167:27 | string indirection | semmle.label | string indirection | -| test.cpp:171:17:171:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:171:22:171:27 | string | semmle.label | string | -| test.cpp:171:22:171:27 | string indirection | semmle.label | string indirection | | test.cpp:175:17:175:19 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:175:22:175:27 | string | semmle.label | string | | test.cpp:175:22:175:27 | string indirection | semmle.label | string indirection | -| test.cpp:179:17:179:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:179:22:179:27 | string | semmle.label | string | -| test.cpp:179:22:179:27 | string indirection | semmle.label | string indirection | -| test.cpp:183:17:183:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:183:22:183:27 | string | semmle.label | string | -| test.cpp:183:22:183:27 | string indirection | semmle.label | string indirection | | test.cpp:187:17:187:19 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:187:22:187:27 | string | semmle.label | string | | test.cpp:187:22:187:27 | string indirection | semmle.label | string indirection | -| test.cpp:191:17:191:19 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:191:22:191:27 | string | semmle.label | string | -| test.cpp:191:22:191:27 | string indirection | semmle.label | string indirection | | test.cpp:195:17:195:19 | str indirection [string] | semmle.label | str indirection [string] | | test.cpp:195:22:195:27 | string | semmle.label | string | | test.cpp:195:22:195:27 | string indirection | semmle.label | string indirection | @@ -405,6 +160,8 @@ nodes | test.cpp:243:16:243:21 | string indirection | semmle.label | string indirection | | test.cpp:249:20:249:27 | call to my_alloc | semmle.label | call to my_alloc | | test.cpp:250:12:250:12 | p | semmle.label | p | +| test.cpp:256:17:256:22 | call to malloc | semmle.label | call to malloc | +| test.cpp:257:12:257:12 | p | semmle.label | p | subpaths | test.cpp:242:22:242:27 | buffer | test.cpp:235:40:235:45 | buffer | test.cpp:236:12:236:17 | p_str indirection [post update] [string] | test.cpp:242:16:242:19 | set_string output argument [string] | #select @@ -423,6 +180,5 @@ subpaths | test.cpp:199:9:199:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:199:22:199:27 | string | This write may overflow $@ by 2 elements. | test.cpp:199:22:199:27 | string | string | | test.cpp:203:9:203:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:203:22:203:27 | string | This write may overflow $@ by 2 elements. | test.cpp:203:22:203:27 | string | string | | test.cpp:207:9:207:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:207:22:207:27 | string | This write may overflow $@ by 3 elements. | test.cpp:207:22:207:27 | string | string | -| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 32 elements. | test.cpp:232:10:232:15 | buffer | buffer | | test.cpp:243:5:243:10 | call to memset | test.cpp:241:27:241:32 | call to malloc | test.cpp:243:12:243:21 | string | This write may overflow $@ by 1 element. | test.cpp:243:16:243:21 | string | string | | test.cpp:250:5:250:10 | call to memset | test.cpp:249:20:249:27 | call to my_alloc | test.cpp:250:12:250:12 | p | This write may overflow $@ by 1 element. | test.cpp:250:12:250:12 | p | p | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp index 8a7afb1a4a3..7c73a357c55 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp @@ -229,7 +229,7 @@ void repeated_alerts(unsigned size, unsigned offset) { while(unknown()) { ++size; } - memset(buffer, 0, size); // BAD + memset(buffer, 0, size); // BAD [NOT DETECTED] } void set_string(string_t* p_str, char* buffer) { @@ -248,4 +248,12 @@ void* my_alloc(unsigned size); void foo(unsigned size) { int* p = (int*)my_alloc(size); // BAD memset(p, 0, size + 1); +} + +void test6(unsigned long n, char *p) { + while (unknown()) { + n++; + p = (char *)malloc(n); + memset(p, 0, n); // GOOD + } } \ No newline at end of file diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected index 011b1f8e161..59d89316088 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected @@ -653,6 +653,7 @@ edges | test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:6 | xs | | test.cpp:308:5:308:6 | xs | test.cpp:308:5:308:11 | access to array | | test.cpp:308:5:308:11 | access to array | test.cpp:308:5:308:29 | Store: ... = ... | +subpaths #select | test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size | | test.cpp:8:14:8:21 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:8:14:8:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp index 4536e2bd2e6..e18b630c26f 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp @@ -304,7 +304,7 @@ void test21() { void** xs = new void*[n]; for (int i = 0; i < n; i += 2) { - xs[i] = test21_get(i); - xs[i+1] = test21_get(i+1); + xs[i] = test21_get(i); // GOOD + xs[i+1] = test21_get(i+1); // GOOD [FALSE POSITIVE] } } diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected index 26b2bd0351d..4922e0641fd 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected @@ -125,6 +125,8 @@ postWithInFlow | test.cpp:681:3:681:3 | s [post update] | PostUpdateNode should not be the target of local flow. | | test.cpp:689:3:689:3 | s [post update] | PostUpdateNode should not be the target of local flow. | | test.cpp:690:3:690:3 | s [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:694:4:694:6 | buf [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:704:23:704:25 | buf [inner post update] | PostUpdateNode should not be the target of local flow. | viableImplInCallContextTooLarge uniqueParameterNodeAtPosition uniqueParameterNodePosition diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp index 5fae604f4d9..bb7919f5a68 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp @@ -690,3 +690,16 @@ void test_static_local_9() { s = 0; } +void increment_buf(int** buf) { // $ ast-def=buf ir-def=*buf ir-def=**buf + *buf += 10; + sink(buf); // $ SPURIOUS: ast,ir // should only be flow to the indirect argument, but there's also flow to the non-indirect argument +} + +void call_increment_buf(int** buf) { // $ ast-def=buf + increment_buf(buf); +} + +void test_conflation_regression(int* source) { // $ ast-def=source + int* buf = source; + call_increment_buf(&buf); +} \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md b/csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md new file mode 100644 index 00000000000..4d4f0767238 --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `cs/log-forging`, `cs/cleartext-storage`, and `cs/exposure-of-sensitive-information` queries now correctly handle unsanitized arguments to `ILogger` extension methods. diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll index 26b75f06269..d19b0006eb7 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll @@ -26,7 +26,14 @@ private class ExternalModelSink extends ExternalLocationSink { * An argument to a call to a method on a logger class. */ class LogMessageSink extends ExternalLocationSink { - LogMessageSink() { this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument() } + LogMessageSink() { + this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument() + or + this.getExpr() = + any(ExtensionMethodCall call | + call.getTarget().(ExtensionMethod).getExtendedType() instanceof LoggerType + ).getArgument(any(int i | i > 0)) + } } /** diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs index 7f307e390ea..05772dfb29a 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs @@ -214,4 +214,25 @@ namespace My.Qltest static void Sink(object o) { } } + + public interface HI { } + + public class HC : HI { } + + public static class HE + { + public static object ExtensionMethod(this HI h) => throw null; + } + + public class H + { + void M1() + { + var h = new HC(); + var o = h.ExtensionMethod(); + Sink(o); + } + + static void Sink(object o) { } + } } \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected index 25267c71e87..09ce9945cdf 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected @@ -70,6 +70,9 @@ edges | ExternalFlow.cs:197:42:197:43 | access to local variable o2 : Object | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | | ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | +| ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | ExternalFlow.cs:232:21:232:21 | access to local variable h : HC | +| ExternalFlow.cs:232:21:232:21 | access to local variable h : HC | ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC | +| ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC | ExternalFlow.cs:233:18:233:18 | access to local variable o | nodes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | semmle.label | call to method StepArgRes | @@ -162,6 +165,10 @@ nodes | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | semmle.label | call to method MixedFlowArgs | | ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object | +| ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | semmle.label | object creation of type HC : HC | +| ExternalFlow.cs:232:21:232:21 | access to local variable h : HC | semmle.label | access to local variable h : HC | +| ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC | semmle.label | call to method ExtensionMethod : HC | +| ExternalFlow.cs:233:18:233:18 | access to local variable o | semmle.label | access to local variable o | subpaths #select | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | $@ | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | object creation of type Object : Object | @@ -188,3 +195,4 @@ subpaths | ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | $@ | ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | $@ | ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | $@ | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | object creation of type Object : Object | +| ExternalFlow.cs:233:18:233:18 | access to local variable o | ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | ExternalFlow.cs:233:18:233:18 | access to local variable o | $@ | ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | object creation of type HC : HC | diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml index 99d387e5ebe..f626949e6f4 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml @@ -29,3 +29,4 @@ extensions: - ["My.Qltest", "G", false, "GeneratedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "df-generated"] - ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"] - ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "manual"] + - ["My.Qltest", "HE", false, "ExtensionMethod", "(My.Qltest.HI)", "", "Argument[0]", "ReturnValue", "value", "manual"] diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs index aac9ce65523..d3253f4a440 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.IO; using System.Net; using System.Web; +using Microsoft.Extensions.Logging; class ILogger { @@ -24,6 +25,10 @@ public class LogForgingHandler : IHttpHandler logger.Warn(WebUtility.HtmlEncode(username) + " logged in"); // BAD: Logged as-is to TraceSource new TraceSource("Test").TraceInformation(username + " logged in"); + + Microsoft.Extensions.Logging.ILogger logger2 = null; + // BAD: Logged as-is + logger2.LogError(username); } public bool IsReusable diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected index cfae0ac589e..5724f73d55b 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected @@ -1,19 +1,23 @@ edges -| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:17:27:17:61 | access to indexer : String | -| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:20:21:20:43 | ... + ... | -| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:26:50:26:72 | ... + ... | -| LogForging.cs:17:27:17:61 | access to indexer : String | LogForging.cs:20:21:20:43 | ... + ... | -| LogForging.cs:17:27:17:61 | access to indexer : String | LogForging.cs:26:50:26:72 | ... + ... | +| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:27:18:61 | access to indexer : String | +| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:21:21:21:43 | ... + ... | +| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:27:50:27:72 | ... + ... | +| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:31:26:31:33 | access to local variable username | +| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:21:21:21:43 | ... + ... | +| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:27:50:27:72 | ... + ... | +| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:31:26:31:33 | access to local variable username | | LogForgingAsp.cs:8:32:8:39 | username : String | LogForgingAsp.cs:12:21:12:43 | ... + ... | nodes -| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection | -| LogForging.cs:17:27:17:61 | access to indexer : String | semmle.label | access to indexer : String | -| LogForging.cs:20:21:20:43 | ... + ... | semmle.label | ... + ... | -| LogForging.cs:26:50:26:72 | ... + ... | semmle.label | ... + ... | +| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection | +| LogForging.cs:18:27:18:61 | access to indexer : String | semmle.label | access to indexer : String | +| LogForging.cs:21:21:21:43 | ... + ... | semmle.label | ... + ... | +| LogForging.cs:27:50:27:72 | ... + ... | semmle.label | ... + ... | +| LogForging.cs:31:26:31:33 | access to local variable username | semmle.label | access to local variable username | | LogForgingAsp.cs:8:32:8:39 | username : String | semmle.label | username : String | | LogForgingAsp.cs:12:21:12:43 | ... + ... | semmle.label | ... + ... | subpaths #select -| LogForging.cs:20:21:20:43 | ... + ... | LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:20:21:20:43 | ... + ... | This log entry depends on a $@. | LogForging.cs:17:27:17:49 | access to property QueryString | user-provided value | -| LogForging.cs:26:50:26:72 | ... + ... | LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:26:50:26:72 | ... + ... | This log entry depends on a $@. | LogForging.cs:17:27:17:49 | access to property QueryString | user-provided value | +| LogForging.cs:21:21:21:43 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:21:21:21:43 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value | +| LogForging.cs:27:50:27:72 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:27:50:27:72 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value | +| LogForging.cs:31:26:31:33 | access to local variable username | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:31:26:31:33 | access to local variable username | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value | | LogForgingAsp.cs:12:21:12:43 | ... + ... | LogForgingAsp.cs:8:32:8:39 | username : String | LogForgingAsp.cs:12:21:12:43 | ... + ... | This log entry depends on a $@. | LogForgingAsp.cs:8:32:8:39 | username | user-provided value | diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst index 8c9c6d8cffa..6742dfa8e76 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst @@ -193,7 +193,7 @@ The class `ASTNode `__, the standard Node.js ``http`` and ``https`` modules, `Connect `__, `Koa `__, `Hapi `__ and `Restify `__. diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index ac60ea55c1b..744a21ceaf1 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -176,7 +176,11 @@ A QL module definition has the following syntax: :: - module ::= annotation* "module" modulename "{" moduleBody "}" + module ::= annotation* "module" modulename parameters? implements? "{" moduleBody "}" + + parameters ::= "<" signatureExpr simpleId ("," signatureExpr simpleId)* ">" + + implements ::= "implements" moduleSignatureExpr ("," moduleSignatureExpr)* moduleBody ::= (import | predicate | class | module | alias | select)* @@ -208,12 +212,15 @@ An import directive refers to a module identifier: :: - import ::= annotations "import" importModuleId ("as" modulename)? + import ::= annotations "import" importModuleExpr ("as" modulename)? qualId ::= simpleId | qualId "." simpleId - importModuleId ::= qualId - | importModuleId "::" simpleId + importModuleExpr ::= qualId | importModuleExpr "::" simpleId arguments? + + arguments ::= "<" argument ("," argument)* ">" + + argument ::= moduleExpr | type | predicateRef "/" int An import directive may optionally name the imported module using an ``as`` declaration. If a name is defined, then the import directive adds to the declared module environment of the current module a mapping from the name to the declaration of the imported module. Otherwise, the current module *directly imports* the imported module. @@ -280,9 +287,9 @@ With the exception of class domain types and character types (which cannot be re :: - type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string" + type ::= (moduleExpr "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string" - moduleId ::= simpleId | moduleId "::" simpleId + moduleExpr ::= simpleId arguments? | moduleExpr "::" simpleId arguments? A type reference is resolved to a type as follows: @@ -597,7 +604,7 @@ Identifiers are used in following syntactic constructs: modulename ::= simpleId classname ::= upperId dbasetype ::= atLowerId - predicateRef ::= (moduleId "::")? literalId + predicateRef ::= (moduleExpr "::")? literalId predicateName ::= lowerId varname ::= lowerId literalId ::= lowerId | atLowerId @@ -1615,7 +1622,7 @@ Aliases define new names for existing QL entities. alias ::= qldoc? annotations "predicate" literalId "=" predicateRef "/" int ";" | qldoc? annotations "class" classname "=" type ";" - | qldoc? annotations "module" modulename "=" moduleId ";" + | qldoc? annotations "module" modulename "=" moduleExpr ";" An alias introduces a binding from the new name to the entity referred to by the right-hand side in the current module's declared predicate, type, or module environment respectively. @@ -2064,16 +2071,23 @@ The complete grammar for QL is as follows: ql ::= qldoc? moduleBody - module ::= annotation* "module" modulename "{" moduleBody "}" + module ::= annotation* "module" modulename parameters? implements? "{" moduleBody "}" + + parameters ::= "<" signatureExpr simpleId ("," signatureExpr simpleId)* ">" + + implements ::= "implements" moduleSignatureExpr ("," moduleSignatureExpr)* moduleBody ::= (import | predicate | class | module | alias | select)* - import ::= annotations "import" importModuleId ("as" modulename)? + import ::= annotations "import" importModuleExpr ("as" modulename)? qualId ::= simpleId | qualId "." simpleId - importModuleId ::= qualId - | importModuleId "::" simpleId + importModuleExpr ::= qualId | importModuleExpr "::" simpleId arguments? + + arguments ::= "<" argument ("," argument)* ">" + + argument ::= moduleExpr | type | predicateRef "/" int select ::= ("from" var_decls)? ("where" formula)? "select" as_exprs ("order" "by" orderbys)? @@ -2120,15 +2134,19 @@ The complete grammar for QL is as follows: field ::= qldoc? annotations var_decl ";" - moduleId ::= simpleId | moduleId "::" simpleId + moduleExpr ::= simpleId arguments? | moduleExpr "::" simpleId arguments? - type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string" + moduleSignatureExpr ::= (moduleExpr "::")? upperId arguments? + + signatureExpr : (moduleExpr "::")? simpleId ("/" Integer | arguments)?; + + type ::= (moduleExpr "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string" exprs ::= expr ("," expr)* alias ::= qldoc? annotations "predicate" literalId "=" predicateRef "/" int ";" | qldoc? annotations "class" classname "=" type ";" - | qldoc? annotations "module" modulename "=" moduleId ";" + | qldoc? annotations "module" modulename "=" moduleExpr ";" var_decls ::= (var_decl ("," var_decl)*)? @@ -2249,7 +2267,7 @@ The complete grammar for QL is as follows: dbasetype ::= atLowerId - predicateRef ::= (moduleId "::")? literalId + predicateRef ::= (moduleExpr "::")? literalId predicateName ::= lowerId diff --git a/go/Makefile b/go/Makefile index 8950bac6a21..7e119b36f03 100644 --- a/go/Makefile +++ b/go/Makefile @@ -113,9 +113,9 @@ ql/lib/go.dbscheme.stats: ql/lib/go.dbscheme build/stats/src.stamp extractor test: all build/testdb/check-upgrade-path codeql test run -j0 ql/test --search-path build/codeql-extractor-go --consistency-queries ql/test/consistency --compilation-cache=$(cache) - # use GOOS=linux because GOOS=darwin GOARCH=386 is no longer supported +# use GOOS=linux because GOOS=darwin GOARCH=386 is no longer supported env GOOS=linux GOARCH=386 codeql$(EXE) test run -j0 ql/test/query-tests/Security/CWE-681 --search-path build/codeql-extractor-go --consistency-queries ql/test/consistency --compilation-cache=$(cache) - cd extractor; go test -mod=vendor ./... | grep -vF "[no test files]" + cd extractor; go test -mod=vendor ./... bash extractor-smoke-test/test.sh || (echo "Extractor smoke test FAILED"; exit 1) .PHONY: build/testdb/check-upgrade-path diff --git a/go/extractor/cli/go-autobuilder/go-autobuilder_test.go b/go/extractor/cli/go-autobuilder/go-autobuilder_test.go index caaa06e234d..8cb97be17ec 100644 --- a/go/extractor/cli/go-autobuilder/go-autobuilder_test.go +++ b/go/extractor/cli/go-autobuilder/go-autobuilder_test.go @@ -36,45 +36,37 @@ func TestParseGoVersion(t *testing.T) { func TestGetVersionToInstall(t *testing.T) { tests := map[versionInfo]string{ - // checkForUnsupportedVersions() - - // go.mod version below minGoVersion - {"0.0", true, "1.20.3", true}: "", - {"0.0", true, "9999.0", true}: "", - {"0.0", true, "1.2.2", true}: "", - {"0.0", true, "", false}: "", - // go.mod version above maxGoVersion - {"9999.0", true, "1.20.3", true}: "", - {"9999.0", true, "9999.0.1", true}: "", - {"9999.0", true, "1.1", true}: "", - {"9999.0", true, "", false}: "", - // Go installation found with version below minGoVersion - {"1.20", true, "1.2.2", true}: "1.20", - {"1.11", true, "1.2.2", true}: "1.11", + // getVersionWhenGoModVersionNotFound() + {"", false, "", false}: maxGoVersion, {"", false, "1.2.2", true}: maxGoVersion, - // Go installation found with version above maxGoVersion + {"", false, "9999.0.1", true}: maxGoVersion, + {"", false, "1.11.13", true}: "", + {"", false, "1.20.3", true}: "", + + // getVersionWhenGoModVersionTooHigh() + {"9999.0", true, "", false}: maxGoVersion, + {"9999.0", true, "9999.0.1", true}: "", + {"9999.0", true, "1.1", true}: maxGoVersion, + {"9999.0", true, minGoVersion, false}: maxGoVersion, + {"9999.0", true, maxGoVersion, true}: "", + + // getVersionWhenGoModVersionTooLow() + {"0.0", true, "", false}: minGoVersion, + {"0.0", true, "9999.0", true}: minGoVersion, + {"0.0", true, "1.2.2", true}: minGoVersion, + {"0.0", true, "1.20.3", true}: "", + + // getVersionWhenGoModVersionSupported() + {"1.20", true, "", false}: "1.20", + {"1.11", true, "", false}: "1.11", + {"1.20", true, "1.2.2", true}: "1.20", + {"1.11", true, "1.2.2", true}: "1.11", {"1.20", true, "9999.0.1", true}: "1.20", {"1.11", true, "9999.0.1", true}: "1.11", - {"", false, "9999.0.1", true}: maxGoVersion, - - // checkForVersionsNotFound() - - // Go installation not found, go.mod version in supported range - {"1.20", true, "", false}: "1.20", - {"1.11", true, "", false}: "1.11", - // Go installation not found, go.mod not found - {"", false, "", false}: maxGoVersion, - // Go installation found with version in supported range, go.mod not found - {"", false, "1.11.13", true}: "", - {"", false, "1.20.3", true}: "", - - // compareVersions() - - // Go installation found with version in supported range, go.mod version in supported range and go.mod version > go installation version + // go.mod version > go installation version {"1.20", true, "1.11.13", true}: "1.20", {"1.20", true, "1.12", true}: "1.20", - // Go installation found with version in supported range, go.mod version in supported range and go.mod version <= go installation version - // (Note comparisons ignore the patch version) + // go.mod version <= go installation version (Note comparisons ignore the patch version) {"1.11", true, "1.20", true}: "", {"1.11", true, "1.20.3", true}: "", {"1.20", true, "1.20.3", true}: "", diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py index 9def03947b3..1cb00f89f55 100644 --- a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py @@ -8,6 +8,17 @@ if "JAVA_HOME_8_X64" in os.environ: sep = ";" if platform.system() == "Windows" else ":" os.environ["PATH"] = "".join([os.path.join(os.environ["JAVA_HOME"], "bin"), sep, os.environ["PATH"]]) -run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None) +# Ensure the autobuilder *doesn't* see Java 11 or 17, which it could switch to in order to build the project: +for k in ["JAVA_HOME_11_X64", "JAVA_HOME_17_X64"]: + if k in os.environ: + del os.environ[k] + +# Use a custom, empty toolchains.xml file so the autobuilder doesn't see any Java versions that may be +# in a system-level toolchains file +toolchains_path = os.path.join(os.getcwd(), 'toolchains.xml') + +run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None, extra_env={ + 'LGTM_INDEX_MAVEN_TOOLCHAINS_FILE': toolchains_path +}) check_diagnostics() diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/toolchains.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/toolchains.xml new file mode 100644 index 00000000000..51f20003fa9 --- /dev/null +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/toolchains.xml @@ -0,0 +1,5 @@ + + + diff --git a/java/ql/lib/semmle/code/java/security/XmlParsers.qll b/java/ql/lib/semmle/code/java/security/XmlParsers.qll index dd28d8b0117..230b102bd5e 100644 --- a/java/ql/lib/semmle/code/java/security/XmlParsers.qll +++ b/java/ql/lib/semmle/code/java/security/XmlParsers.qll @@ -655,6 +655,11 @@ class XmlReader extends RefType { XmlReader() { this.hasQualifiedName("org.xml.sax", "XMLReader") } } +/** The class `org.xml.sax.InputSource`. */ +class InputSource extends Class { + InputSource() { this.hasQualifiedName("org.xml.sax", "InputSource") } +} + /** DEPRECATED: Alias for XmlReader */ deprecated class XMLReader = XmlReader; @@ -1164,22 +1169,34 @@ class XmlUnmarshal extends XmlParserCall { } /* XPathExpression: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xpathexpression */ -/** The class `javax.xml.xpath.XPathExpression`. */ -class XPathExpression extends RefType { +/** The interface `javax.xml.xpath.XPathExpression`. */ +class XPathExpression extends Interface { XPathExpression() { this.hasQualifiedName("javax.xml.xpath", "XPathExpression") } } -/** A call to `XPathExpression.evaluate`. */ +/** The interface `java.xml.xpath.XPath`. */ +class XPath extends Interface { + XPath() { this.hasQualifiedName("javax.xml.xpath", "XPath") } +} + +/** A call to the method `evaluate` of the classes `XPathExpression` or `XPath`. */ class XPathEvaluate extends XmlParserCall { + Argument sink; + XPathEvaluate() { exists(Method m | this.getMethod() = m and - m.getDeclaringType() instanceof XPathExpression and m.hasName("evaluate") + | + m.getDeclaringType().getASourceSupertype*() instanceof XPathExpression and + sink = this.getArgument(0) + or + m.getDeclaringType().getASourceSupertype*() instanceof XPath and + sink = this.getArgument(1) ) } - override Expr getSink() { result = this.getArgument(0) } + override Expr getSink() { result = sink } override predicate isSafe() { none() } } diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll b/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll index c2d119e8f29..57bd397f7a8 100644 --- a/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll +++ b/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll @@ -27,7 +27,7 @@ abstract class MetadataExtractor extends string { abstract predicate hasMetadata( DataFlow::ParameterNode e, string package, string type, boolean subtypes, string name, - string signature, int input + string signature, int input, string parameterName ); } @@ -167,14 +167,15 @@ class FrameworkModeMetadataExtractor extends MetadataExtractor { override predicate hasMetadata( Endpoint e, string package, string type, boolean subtypes, string name, string signature, - int input + int input, string parameterName ) { exists(Callable callable | e.asParameter() = callable.getParameter(input) and package = callable.getDeclaringType().getPackage().getName() and type = callable.getDeclaringType().getErasure().(RefType).nestedName() and subtypes = this.considerSubtypes(callable) and - name = e.toString() and + name = callable.getName() and + parameterName = e.asParameter().getName() and signature = ExternalFlow::paramsString(callable) ) } diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql index fb0a947379d..a64327422a0 100644 --- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql +++ b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql @@ -17,7 +17,7 @@ private import AutomodelSharedUtil from Endpoint endpoint, string message, MetadataExtractor meta, string package, string type, - boolean subtypes, string name, string signature, int input + boolean subtypes, string name, string signature, int input, string parameterName where not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u | u.appliesToEndpoint(endpoint) @@ -28,7 +28,7 @@ where // overlap between our detected sinks and the pre-existing modeling. We assume that, if a sink has already been // modeled in a MaD model, then it doesn't belong to any additional sink types, and we don't need to reexamine it. not CharacteristicsImpl::isSink(endpoint, _) and - meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and + meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and // The message is the concatenation of all sink types for which this endpoint is known neither to be a sink nor to be // a non-sink, and we surface only endpoints that have at least one such sink type. message = @@ -39,7 +39,7 @@ where sinkType, ", " ) select endpoint, - message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", // + message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // package.(DollarAtString), "package", // @@ -47,4 +47,5 @@ select endpoint, subtypes.toString().(DollarAtString), "subtypes", // name.(DollarAtString), "name", // signature.(DollarAtString), "signature", // - input.toString().(DollarAtString), "input" // + input.toString().(DollarAtString), "input", // + parameterName.(DollarAtString), "parameterName" // diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql index 368a373ffe8..f1ba8ee4119 100644 --- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql +++ b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql @@ -15,7 +15,7 @@ private import AutomodelSharedUtil from Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message, MetadataExtractor meta, string package, string type, boolean subtypes, string name, - string signature, int input + string signature, int input, string parameterName where characteristic.appliesToEndpoint(endpoint) and confidence >= SharedCharacteristics::highConfidence() and @@ -23,7 +23,7 @@ where // Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly // certain about in the prompt. not erroneousEndpoints(endpoint, _, _, _, _, false) and - meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and + meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and // It's valid for a node to satisfy the logic for both `isSink` and `isSanitizer`, but in that case it will be // treated by the actual query as a sanitizer, since the final logic is something like // `isSink(n) and not isSanitizer(n)`. We don't want to include such nodes as negative examples in the prompt, because @@ -36,7 +36,7 @@ where ) and message = characteristic select endpoint, - message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", // + message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // package.(DollarAtString), "package", // @@ -44,4 +44,5 @@ select endpoint, subtypes.toString().(DollarAtString), "subtypes", // name.(DollarAtString), "name", // signature.(DollarAtString), "signature", // - input.toString().(DollarAtString), "input" // + input.toString().(DollarAtString), "input", // + parameterName.(DollarAtString), "parameterName" // diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql index df4d94ce235..e216c292538 100644 --- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql +++ b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql @@ -14,16 +14,16 @@ private import AutomodelSharedUtil from Endpoint endpoint, SinkType sinkType, MetadataExtractor meta, string package, string type, - boolean subtypes, string name, string signature, int input + boolean subtypes, string name, string signature, int input, string parameterName where // Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly // certain about in the prompt. not erroneousEndpoints(endpoint, _, _, _, _, false) and - meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and + meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and // Extract positive examples of sinks belonging to the existing ATM query configurations. CharacteristicsImpl::isKnownSink(endpoint, sinkType) select endpoint, - sinkType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", // + sinkType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // package.(DollarAtString), "package", // @@ -31,4 +31,5 @@ select endpoint, subtypes.toString().(DollarAtString), "subtypes", // name.(DollarAtString), "name", // signature.(DollarAtString), "signature", // - input.toString().(DollarAtString), "input" // + input.toString().(DollarAtString), "input", // + parameterName.(DollarAtString), "parameterName" // diff --git a/java/ql/src/change-notes/2023-05-15-xpath-xxe-sink.md b/java/ql/src/change-notes/2023-05-15-xpath-xxe-sink.md new file mode 100644 index 00000000000..1696ffbd213 --- /dev/null +++ b/java/ql/src/change-notes/2023-05-15-xpath-xxe-sink.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The queries `java/xxe` and `java/xxe-local` now recognize the second argument of calls to `XPath.evaluate` as a sink. diff --git a/java/ql/test/query-tests/security/CWE-611/XPathExpressionTests.java b/java/ql/test/query-tests/security/CWE-611/XPathExpressionTests.java index 1d67b9a055f..e15c28e41e2 100644 --- a/java/ql/test/query-tests/security/CWE-611/XPathExpressionTests.java +++ b/java/ql/test/query-tests/security/CWE-611/XPathExpressionTests.java @@ -12,18 +12,33 @@ public class XPathExpressionTests { public void safeXPathExpression(Socket sock) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - DocumentBuilder builder = factory.newDocumentBuilder(); - XPathFactory xFactory = XPathFactory.newInstance(); - XPath path = xFactory.newXPath(); - XPathExpression expr = path.compile(""); - expr.evaluate(builder.parse(sock.getInputStream())); //safe + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + DocumentBuilder builder = factory.newDocumentBuilder(); + XPathFactory xFactory = XPathFactory.newInstance(); + XPath path = xFactory.newXPath(); + XPathExpression expr = path.compile(""); + expr.evaluate(builder.parse(sock.getInputStream())); // safe } public void unsafeExpressionTests(Socket sock) throws Exception { - XPathFactory xFactory = XPathFactory.newInstance(); - XPath path = xFactory.newXPath(); - XPathExpression expr = path.compile(""); - expr.evaluate(new InputSource(sock.getInputStream())); //unsafe + XPathFactory xFactory = XPathFactory.newInstance(); + XPath path = xFactory.newXPath(); + XPathExpression expr = path.compile(""); + expr.evaluate(new InputSource(sock.getInputStream())); // unsafe + } + + public void safeXPathEvaluateTest(Socket sock) throws Exception { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + DocumentBuilder builder = factory.newDocumentBuilder(); + XPathFactory xFactory = XPathFactory.newInstance(); + XPath path = xFactory.newXPath(); + path.evaluate("", builder.parse(sock.getInputStream())); + } + + public void unsafeXPathEvaluateTest(Socket sock) throws Exception { + XPathFactory xFactory = XPathFactory.newInstance(); + XPath path = xFactory.newXPath(); + path.evaluate("", new InputSource(sock.getInputStream())); // unsafe } } diff --git a/java/ql/test/query-tests/security/CWE-611/XXE.expected b/java/ql/test/query-tests/security/CWE-611/XXE.expected index 6304e3582a2..bfc1eca96c0 100644 --- a/java/ql/test/query-tests/security/CWE-611/XXE.expected +++ b/java/ql/test/query-tests/security/CWE-611/XXE.expected @@ -74,7 +74,8 @@ edges | XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | XMLReaderTests.java:86:18:86:55 | new InputSource(...) | | XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | XMLReaderTests.java:94:18:94:55 | new InputSource(...) | | XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | -| XPathExpressionTests.java:27:37:27:57 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | +| XPathExpressionTests.java:27:35:27:55 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:19:27:56 | new InputSource(...) | +| XPathExpressionTests.java:42:39:42:59 | getInputStream(...) : InputStream | XPathExpressionTests.java:42:23:42:60 | new InputSource(...) | nodes | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | semmle.label | getInputStream(...) | | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | semmle.label | getInputStream(...) | @@ -235,8 +236,10 @@ nodes | XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | semmle.label | new InputSource(...) | | XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | -| XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | semmle.label | new InputSource(...) | -| XPathExpressionTests.java:27:37:27:57 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| XPathExpressionTests.java:27:19:27:56 | new InputSource(...) | semmle.label | new InputSource(...) | +| XPathExpressionTests.java:27:35:27:55 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| XPathExpressionTests.java:42:23:42:60 | new InputSource(...) | semmle.label | new InputSource(...) | +| XPathExpressionTests.java:42:39:42:59 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | semmle.label | getInputStream(...) | | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | semmle.label | getInputStream(...) | | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | semmle.label | getInputStream(...) | @@ -336,7 +339,8 @@ subpaths | XMLReaderTests.java:86:18:86:55 | new InputSource(...) | XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | XMLReaderTests.java:86:18:86:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:86:34:86:54 | getInputStream(...) | user-provided value | | XMLReaderTests.java:94:18:94:55 | new InputSource(...) | XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | XMLReaderTests.java:94:18:94:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:94:34:94:54 | getInputStream(...) | user-provided value | | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:100:34:100:54 | getInputStream(...) | user-provided value | -| XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) | user-provided value | +| XPathExpressionTests.java:27:19:27:56 | new InputSource(...) | XPathExpressionTests.java:27:35:27:55 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:19:27:56 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XPathExpressionTests.java:27:35:27:55 | getInputStream(...) | user-provided value | +| XPathExpressionTests.java:42:23:42:60 | new InputSource(...) | XPathExpressionTests.java:42:39:42:59 | getInputStream(...) : InputStream | XPathExpressionTests.java:42:23:42:60 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XPathExpressionTests.java:42:39:42:59 | getInputStream(...) | user-provided value | | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | user-provided value | | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | user-provided value | | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | user-provided value | diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp index b88457431bf..bb0cd344070 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp @@ -35,8 +35,8 @@

In the example below, the untrusted value req.params.id is used as the property name req.session.todos[id]. If a malicious user passes in the ID value __proto__, - the variable todo will then refer to Object.prototype. - Finally, the modification of todo then allows the attacker to inject arbitrary properties + the variable items will then refer to Object.prototype. + Finally, the modification of items then allows the attacker to inject arbitrary properties onto Object.prototype.

@@ -48,6 +48,12 @@

+ +

+ Another way to fix it is to prevent the __proto__ property from being used as a key, as shown below: +

+ + diff --git a/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignmentFixed2.js b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignmentFixed2.js new file mode 100644 index 00000000000..74bc9a18f24 --- /dev/null +++ b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignmentFixed2.js @@ -0,0 +1,16 @@ +let express = require('express'); +let app = express() + +app.put('/todos/:id', (req, res) => { + let id = req.params.id; + if (id === '__proto__' || id === 'constructor' || id === 'prototype') { + res.end(403); + return; + } + let items = req.session.todos[id]; + if (!items) { + items = req.session.todos[id] = {}; + } + items[req.query.name] = req.query.text; + res.end(200); +}); diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/query17.qll b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/query17.qll index 0b21d872ad6..1de380f710b 100644 --- a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/query17.qll +++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/query17.qll @@ -11,11 +11,8 @@ class PasswordTracker extends DataFlow::Configuration { override predicate isSink(DataFlow::Node nd) { this.passwordVarAssign(_, nd) } predicate passwordVarAssign(Variable v, DataFlow::Node nd) { - exists(SsaExplicitDefinition def | - nd = DataFlow::ssaDefinitionNode(def) and - def.getSourceVariable() = v and - v.getName().toLowerCase() = "password" - ) + v.getAnAssignedExpr() = nd.asExpr() and + v.getName().toLowerCase() = "password" } } diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tests.expected b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tests.expected index 57bfd73841f..bbec34be602 100644 --- a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tests.expected +++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tests.expected @@ -9,6 +9,7 @@ test_query4 | tst.js:29:1:29:5 | 1 + 2 | This expression should be bracketed to clarify precedence rules. | test_query19 test_query17 +| tst.js:38:18:38:23 | "blah" | Password variable password is assigned a constant string. | test_query18 | m.js:1:1:3:0 | | 0 | test_query8 @@ -18,6 +19,7 @@ test_query11 | tst.js:31:12:31:12 | x | Dead store of local variable. | | tst.js:31:15:31:15 | y | Dead store of local variable. | | tst.js:31:18:31:18 | x | Dead store of local variable. | +| tst.js:38:7:38:23 | password = "blah" | Dead store of local variable. | test_query12 test_query20 test_query3 diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tst.js b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tst.js index 804012a2673..0714ee8101a 100644 --- a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tst.js +++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tst.js @@ -32,4 +32,8 @@ function l(x, y, x) { for (i=0;i<10;++i); } -var j, j; \ No newline at end of file +var j, j; + +function foo() { + var password = "blah"; +} diff --git a/misc/scripts/accept-expected-changes-from-ci.py b/misc/scripts/accept-expected-changes-from-ci.py new file mode 100755 index 00000000000..12c1bb21763 --- /dev/null +++ b/misc/scripts/accept-expected-changes-from-ci.py @@ -0,0 +1,472 @@ +#!/usr/bin/env python3 +""" +This script can be used to go over `codeql test run` expected/actual log output from +github actions, and apply patches locally to make the tests pass. + +It works by forming individual patches for each test-failure, and then applying them one +by one. Since Python runs some tests twice (for both Python2 and Python3), we try to do +some simple duplicate patch detection, to avoid failing to apply the same patch twice. + +Use it by checking out an up to date version of your branch, and just run the script (it +will use `gh` cli to figure out what the PR number is). You must have the `gh` cli tool +installed. + +The parsing of logs is somewhat tolerant of output being interleaved with other parallel +execution, but it might fail in some cases ¯\_(ツ)_/¯ + +Code written to hack things together until they work, so don't expect much :D +""" + +import argparse +import sys +import re +import tempfile +from typing import List, Dict, Set, Optional, Any +from pathlib import Path +import subprocess +import logging +import json +from dataclasses import dataclass, field +from datetime import datetime +import os.path +import itertools + +LOGGER = logging.getLogger(Path(__file__).name) + +DEBUG_SAVE_PATCHES = False +DEBUG_LOG_FILE = None + + +def _get_codeql_repo_dir() -> Path: + return Path(__file__).parent.parent.parent + + +CODEQL_REPO_DIR = _get_codeql_repo_dir() + + +def _get_semmle_code_dir() -> Optional[Path]: + guess = CODEQL_REPO_DIR.parent + try: + out = subprocess.check_output( + ["git", "remote", "-v"], + cwd=guess, + ).decode("utf-8") + if "github/semmle-code" in out: + return guess + else: + return None + except subprocess.CalledProcessError: + return None + + +SEMMLE_CODE_DIR = _get_semmle_code_dir() +if SEMMLE_CODE_DIR is None: + LOGGER.warning("Could not find semmle-code repo, will not be able to apply patches for it") + + +@dataclass(frozen=True, eq=True, order=True) +class Patch: + filename: Path + dir: Optional[str] + patch_first_line: str + patch: List[str] = field(hash=False) + + def format_as_patch(self) -> str: + return (f"--- a/{self.filename}\n" + + f"+++ b/{self.filename}\n" + + "\n".join(self.patch) + + "\n" + ) + + +def parse_log_line(log_line: str) -> str: + if '\t' in log_line: + m = re.fullmatch(r"^(?:[^\t]+\t){2}\S+ ?(.*)$", log_line.strip()) + else: + m = re.fullmatch(r"^(?:[^ ]+ )(.*)$", log_line.strip()) + + if not m: + return "" + + return m.group(1) + + +def make_patches_from_log_file(log_file_lines) -> List[Patch]: + # TODO: If the expected output contains `Password=123` this will be masked as `***` + # in the actions logs. We _could_ try to detect this and replace the line with the + # actual content from file (but it would require parsing the @@ lines, to understand + # what the old linenumber to read is) + patches = [] + + lines = iter(log_file_lines) + + for raw_line in lines: + line = parse_log_line(raw_line) + + if line == "--- expected": + while True: + next_line = parse_log_line(next(lines)) + if next_line == "+++ actual": + break + + lines_changed = [] + + while True: + next_line = parse_log_line(next(lines)) + # it can be the case that + if next_line[0] in (" ", "-", "+", "@"): + lines_changed.append(next_line) + if "FAILED" in next_line: + break + + # error line _should_ be next, but sometimes the output gets interleaved... + # so we just skip until we find the error line + error_line = next_line + while True: + # internal + filename_match = re.fullmatch(r"^##\[error\].*FAILED\(RESULT\) (.*)$", error_line) + if not filename_match: + # codeql action + filename_match = re.fullmatch(r"^.*FAILED\(RESULT\) (.*)$", error_line) + if filename_match: + break + error_line = parse_log_line(next(lines)) + + full_path = filename_match.group(1) + + known_start_paths = { + # internal CI runs + "/home/runner/work/semmle-code/semmle-code/ql/": CODEQL_REPO_DIR, + "/home/runner/work/semmle-code/semmle-code/target/codeql-java-integration-tests/ql/": CODEQL_REPO_DIR, + "/home/runner/work/semmle-code/semmle-code/" : SEMMLE_CODE_DIR, + # github actions on codeql repo + "/home/runner/work/codeql/codeql/": CODEQL_REPO_DIR, + "/Users/runner/work/codeql/codeql/" : CODEQL_REPO_DIR, # MacOS + } + for known_start_path, dir in known_start_paths.items(): + if full_path.startswith(known_start_path): + filename = Path(full_path[len(known_start_path):]) + break + else: + raise Exception(f"Unknown path {full_path}, skipping") + + expected_filename = filename.with_suffix(".expected") + + # if the .expected file used to be empty, `codeql test run` outputs a diff + # that uses `@@ -1,1 ` but git wants it to be `@@ -0,0 ` (and not include + # the removal of the empty line) + if lines_changed[0].startswith("@@ -1,1 ") and lines_changed[1] == "-": + lines_changed[0] = lines_changed[0].replace("@@ -1,1 ", "@@ -0,0 ") + del lines_changed[1] + + patch = Patch( + filename=expected_filename, + dir=dir, + patch_first_line=lines_changed[0], + patch=lines_changed, + ) + patches.append(patch) + + return patches + +def make_github_api_list_request(path: str) -> Any: + """Handles the way paginate currently works, which is to return multiple lists of + results, instead of merging them :( + """ + + s = subprocess.check_output( + ["gh", "api", "--paginate", path], + ).decode("utf-8") + + try: + return json.loads(s) + except json.JSONDecodeError: + assert "][" in s + parts = s.split("][") + parts[0] = parts[0] + "]" + parts[-1] = "[" + parts[-1] + for i in range(1, len(parts) - 1): + parts[i] = "[" + parts[i] + "]" + return itertools.chain(*[json.loads(x) for x in parts]) + + +@dataclass +class GithubStatus(): + state: str + context: str + target_url: str + created_at: datetime + nwo: str + job_id: int = None + + +def get_log_content(status: GithubStatus) -> str: + LOGGER.debug(f"'{status.context}': Getting logs") + if status.job_id: + content = subprocess.check_output( + ["gh", "api", f"/repos/{status.nwo}/actions/jobs/{status.job_id}/logs"], + ).decode("utf-8") + else: + m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)(?:/jobs/(\d+))?$", status.target_url) + nwo = m.group(1) + run_id = m.group(2) + content = subprocess.check_output( + ["gh", "run", "view", "--repo", nwo, run_id, "--log-failed"], + ).decode("utf-8") + + if DEBUG_SAVE_PATCHES: + tmp = tempfile.NamedTemporaryFile(delete=False) + tmp.write(content.encode(encoding="utf-8")) + print(tmp.name) + return content + + +def main(pr_number: Optional[int], sha_override: Optional[str] = None, force=False): + if not pr_number and not sha_override: + raise Exception("Must specify either a PR number or a SHA") + + if sha_override: + github_sha = sha_override + else: + LOGGER.info(f"Getting status URL for codeql PR #{pr_number}") + github_sha = subprocess.check_output( + ["gh", "api", f"repos/github/codeql/pulls/{pr_number}", "--jq", ".head.sha"] + ).decode("utf-8").strip() + + local_sha = subprocess.check_output( + ["git", "rev-parse", "HEAD"] + ).decode("utf-8").strip() + + if local_sha != github_sha and not force: + LOGGER.error(f"GitHub SHA ({github_sha}) different from your local SHA ({local_sha}), sync your changes first!") + sys.exit(1) + sha = github_sha + + status_url = f"https://api.github.com/repos/github/codeql/commits/{sha}/statuses" + LOGGER.info(f"Getting status details ({status_url})") + statuses = make_github_api_list_request(status_url) + newest_status: Dict[str, GithubStatus] = dict() + + for status in statuses: + created_at = datetime.fromisoformat(status["created_at"][:-1]) + key = status["context"] + if key not in newest_status or created_at > newest_status[key].created_at: + m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)(?:/jobs/(\d+))?$", status["target_url"]) + + newest_status[key] = GithubStatus( + state=status["state"], + context=status["context"], + target_url=status["target_url"], + created_at=created_at, + nwo=m.group(1), + ) + + supported_internal_status_language_test_names = [ + "Java Integration Tests Linux", + # "codeql-coding-standards Unit Tests Linux", + # TODO: Currently disabled, would just require support for figuring out where + # https://github.com/github/codeql-coding-standards/ is checked out locally + ] + + lang_test_failures: List[GithubStatus] = list() + for status in newest_status.values(): + if " Language Tests" in status.context or status.context in supported_internal_status_language_test_names: + if status.state == "failure": + lang_test_failures.append(status) + elif status.state == "pending": + LOGGER.error(f"Language tests ({status.context}) are still running, please wait for them to finish before running this script again") + sys.exit(1) + + job_failure_urls = set() + for lang_test_failure in lang_test_failures: + job_failure_urls.add(lang_test_failure.target_url) + + if job_failure_urls: + assert len(job_failure_urls) == 1, f"Multiple job failure URLs: {job_failure_urls}" + job_failure_url = job_failure_urls.pop() + + # fixup URL. On the status, the target URL is the run, and it's really hard to + # change this to link to the full `/runs//jobs/` URL, since + # the `` is not available in a context: https://github.com/community/community/discussions/40291 + m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)$", job_failure_url) + nwo = m.group(1) + run_id = m.group(2) + jobs_url = f"https://api.github.com/repos/{nwo}/actions/runs/{run_id}/jobs" + LOGGER.info(f"Fixing up target url from looking at {jobs_url}") + jobs = json.loads(subprocess.check_output(["gh", "api", "--paginate", jobs_url]).decode("utf-8")) + for lang_test_failure in lang_test_failures: + workflow_translation = { + "codeql-coding-standards Unit Tests Linux": "Start codeql-coding-standards" + } + expected_workflow_name = workflow_translation.get(lang_test_failure.context, lang_test_failure.context) + + for job in jobs["jobs"]: + api_name: str = job["name"] + if " / " not in api_name: + continue + + workflow_name, job_name = api_name.split(" / ") + # The job names we're looking for looks like "Python2 Language Tests / Python2 Language Tests" or "Java Language Tests / Java Language Tests Linux" + # for "Java Integration Tests Linux / Java Integration tests Linux" we need to ignore case :| + if workflow_name == expected_workflow_name and job_name.lower().startswith(lang_test_failure.context.lower()): + lang_test_failure.job_id = job["id"] + break + else: + LOGGER.error(f"Could not find job for {lang_test_failure.context!r}") + sys.exit(1) + + # Ruby/Swift/C#/Go use github actions, and not internal CI. These are not reported + # from the /statuses API, but from the /check-suites API + check_suites_url = f"https://api.github.com/repos/github/codeql/commits/{sha}/check-suites" + LOGGER.info(f"Getting check suites ({check_suites_url})") + check_suites = json.loads(subprocess.check_output(["gh", "api", "--paginate", check_suites_url]).decode("utf-8")) + + check_failure_urls = [] + for check in check_suites["check_suites"]: + if check["status"] != "completed": + print(check) + LOGGER.error("At least one check not completed yet!") + sys.exit(1) + + if check["conclusion"] == "failure": + check_failure_urls.append(check["check_runs_url"]) + + for check_failure_url in check_failure_urls: + # run information: https://docs.github.com/en/rest/actions/workflow-jobs?apiVersion=2022-11-28#get-a-job-for-a-workflow-run + check_runs = json.loads(subprocess.check_output(["gh", "api", "--paginate", check_failure_url]).decode("utf-8")) + for check_run in check_runs["check_runs"]: + if check_run["conclusion"] == "failure": + m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)(?:/jobs/(\d+))?$", check_run["details_url"]) + nwo = m.group(1) + run_id = m.group(2) + jobs_url = f"https://api.github.com/repos/{nwo}/actions/runs/{run_id}/jobs" + LOGGER.debug(f"Looking into failure at {jobs_url}") + jobs = json.loads(subprocess.check_output(["gh", "api", "--paginate", jobs_url]).decode("utf-8")) + + for job in jobs["jobs"]: + OK_WORKFLOW_NAMES = ["C#: Run QL Tests", "Go: Run Tests", "Ruby: Run QL Tests", "Swift"] + def ok_job_name(job_name: str) -> bool: + if job_name.startswith("qltest"): + return True + if job_name.startswith("Test Linux"): + return True + if job_name.startswith("integration-tests"): + return True + return False + + if job["name"] == check_run['name'] and job["workflow_name"] in OK_WORKFLOW_NAMES and ok_job_name(job["name"]): + # print(check_run['name'], 'matched to', f"{job['workflow_name']} / {job['name']}") + lang_test_failures.append(GithubStatus( + state="failure", + context=f"{job['workflow_name']} / {job['name']}", + target_url=job["html_url"], + created_at=check_run["completed_at"], + nwo=nwo, + job_id=job["id"], + )) + break + else: + LOGGER.debug(f"Ignoring actions failure for '{check_run['name']}' ({check_run['details_url']})") + + if not lang_test_failures: + LOGGER.info("No language test failures found") + return + + patches_to_apply: Set[Patch] = set() + + for failure in lang_test_failures: + log_content = get_log_content(failure) + LOGGER.info(f"'{failure.context}': Making patches") + patches = make_patches_from_log_file(log_content.splitlines()) + + if not patches: + LOGGER.warning(f"No patches generated for job {failure}") + continue + + for patch in patches: + if patch in patches_to_apply: + LOGGER.debug(f"Skipping duplicate patch for {patch.filename}") + continue + patches_to_apply.add(patch) + + if DEBUG_SAVE_PATCHES: + sys.exit("debug save patches") + + if not patches_to_apply: + print("No patches to apply") + return + + semmle_code_changed = False + + for patch in patches_to_apply: + with tempfile.NamedTemporaryFile(prefix=f"patches-", suffix=".patch") as temp: + temp.write(patch.format_as_patch().encode(encoding="utf-8")) + temp.flush() + LOGGER.info(f"Applying patch for '{patch.filename}'") + try: + if patch.dir is None: + LOGGER.warning(f"Did not find local semmle-code directory, so skipping patch for '{patch.filename}'") + continue + + subprocess.check_call(["git", "apply", temp.name], cwd=patch.dir) + + if "CONSISTENCY" in patch.filename.parts: + # delete if empty + if os.path.getsize(patch.filename) == 1 and patch.filename.read_text() == "\n": + os.remove(patch.filename) + LOGGER.info(f"Deleted empty CONSISTENCY file '{patch.filename}'") + + if patch.dir == SEMMLE_CODE_DIR: + semmle_code_changed = True + except subprocess.CalledProcessError: + LOGGER.error(f"Could not apply patches for '{patch.filename}' '{patch.patch[0]}', skipping") + tmp_keep = tempfile.NamedTemporaryFile(delete=False) + tmp_keep.write(patch.format_as_patch().encode(encoding="utf-8")) + LOGGER.error(f"Patch saved to {tmp_keep.name}") + + if semmle_code_changed: + print("Expected output in semmle-code changed!") + + +if __name__ == "__main__": + + level = logging.INFO + + try: + import coloredlogs + coloredlogs.install(level, fmt="%(levelname)s: %(message)s") + except ImportError: + logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") + + # parse command line arguments + parser = argparse.ArgumentParser() + parser.add_argument("--force", action="store_true", help="Apply patches even if the local SHA is different from the GitHub PR SHA") + parser.add_argument("posarg", nargs="?", default=None) + + if DEBUG_LOG_FILE: + patches = make_patches_from_log_file(open(DEBUG_LOG_FILE, "r").readlines()) + for patch in patches: + if True: + tmp_keep = tempfile.NamedTemporaryFile(delete=False) + tmp_keep.write(patch.format_as_patch().encode(encoding="utf-8")) + LOGGER.info(f"Patch for {patch.filename} saved to {tmp_keep.name}") + sys.exit(1) + + os.chdir(CODEQL_REPO_DIR) + + pr_number = None + override_sha = None + args = parser.parse_args() + + if args.posarg is None: + pr_number_response = subprocess.check_output([ + "gh", "pr", "view", "--json", "number" + ]).decode("utf-8") + pr_number = json.loads(pr_number_response)["number"] + else: + if len(args.posarg) > 10: + override_sha = args.posarg + else: + pr_number = int(args.posarg) + + main(pr_number, override_sha, force=args.force) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll index f7b5fc45f09..3b32d95ae0b 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll @@ -1,6 +1,7 @@ private import python private import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate +private import FlowSummaryImpl as FlowSummaryImpl private import semmle.python.dataflow.new.internal.TaintTrackingPublic private import semmle.python.ApiGraphs @@ -55,6 +56,8 @@ private module Cached { awaitStep(nodeFrom, nodeTo) or asyncWithStep(nodeFrom, nodeTo) + or + FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false) } } @@ -159,7 +162,7 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT * is currently very imprecise, as an example, since we model `dict.get`, we treat any * `.get()` will be tainted, whether it's true or not. */ -predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::Node nodeTo) { +predicate containerStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { // construction by literal // // TODO: once we have proper flow-summary modeling, we might not need this step any @@ -181,13 +184,6 @@ predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::Node nodeTo) { // don't provide that right now. DataFlowPrivate::comprehensionStoreStep(nodeFrom, _, nodeTo) or - // constructor call - exists(DataFlow::CallCfgNode call | call = nodeTo | - call = API::builtin(["list", "set", "frozenset", "dict", "tuple"]).getACall() and - call.getArg(0) = nodeFrom - // TODO: Properly handle defaultdict/namedtuple - ) - or // functions operating on collections exists(DataFlow::CallCfgNode call | call = nodeTo | call = API::builtin(["sorted", "reversed", "iter", "next"]).getACall() and diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll index 52807799c2c..d4d9e1f31f5 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll @@ -613,8 +613,17 @@ class TypeBackTracker extends TTypeBackTracker { * also flow to `sink`. */ TypeTracker getACompatibleTypeTracker() { - exists(boolean hasCall | result = MkTypeTracker(hasCall, content) | - hasCall = false or this.hasReturn() = false + exists(boolean hasCall, OptionalTypeTrackerContent c | + result = MkTypeTracker(hasCall, c) and + ( + compatibleContents(c, content) + or + content = noContent() and c = content + ) + | + hasCall = false + or + this.hasReturn() = false ) } } diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 7e62a5b033e..cd5ec31945e 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -3790,6 +3790,138 @@ private module StdlibPrivate { override DataFlow::Node getAPathArgument() { result = this.getAnInput() } } + // --------------------------------------------------------------------------- + // Flow summaries for functions contructing containers + // --------------------------------------------------------------------------- + /** A flow summary for `dict`. */ + class DictSummary extends SummarizedCallable { + DictSummary() { this = "builtins.dict" } + + override DataFlow::CallCfgNode getACall() { result = API::builtin("dict").getACall() } + + override DataFlow::ArgumentNode getACallback() { + result = API::builtin("dict").getAValueReachableFromSource() + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() | + input = "Argument[0].DictionaryElement[" + key + "]" and + output = "ReturnValue.DictionaryElement[" + key + "]" and + preservesValue = true + ) + or + exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() | + input = "Argument[" + key + ":]" and + output = "ReturnValue.DictionaryElement[" + key + "]" and + preservesValue = true + ) + or + input = "Argument[0]" and + output = "ReturnValue" and + preservesValue = false + } + } + + /** A flow summary for `list`. */ + class ListSummary extends SummarizedCallable { + ListSummary() { this = "builtins.list" } + + override DataFlow::CallCfgNode getACall() { result = API::builtin("list").getACall() } + + override DataFlow::ArgumentNode getACallback() { + result = API::builtin("list").getAValueReachableFromSource() + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + ( + input = "Argument[0].ListElement" + or + input = "Argument[0].SetElement" + or + exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() | + input = "Argument[0].TupleElement[" + i.toString() + "]" + ) + // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent + ) and + output = "ReturnValue.ListElement" and + preservesValue = true + or + input = "Argument[0]" and + output = "ReturnValue" and + preservesValue = false + } + } + + /** A flow summary for tuple */ + class TupleSummary extends SummarizedCallable { + TupleSummary() { this = "builtins.tuple" } + + override DataFlow::CallCfgNode getACall() { result = API::builtin("tuple").getACall() } + + override DataFlow::ArgumentNode getACallback() { + result = API::builtin("tuple").getAValueReachableFromSource() + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() | + input = "Argument[0].TupleElement[" + i.toString() + "]" and + output = "ReturnValue.TupleElement[" + i.toString() + "]" and + preservesValue = true + ) + or + // TODO: We need to also translate iterable content such as list element + // but we currently lack TupleElementAny + input = "Argument[0]" and + output = "ReturnValue" and + preservesValue = false + } + } + + /** A flow summary for set */ + class SetSummary extends SummarizedCallable { + SetSummary() { this = "builtins.set" } + + override DataFlow::CallCfgNode getACall() { result = API::builtin("set").getACall() } + + override DataFlow::ArgumentNode getACallback() { + result = API::builtin("set").getAValueReachableFromSource() + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + ( + input = "Argument[0].ListElement" + or + input = "Argument[0].SetElement" + or + exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() | + input = "Argument[0].TupleElement[" + i.toString() + "]" + ) + // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent + ) and + output = "ReturnValue.SetElement" and + preservesValue = true + or + input = "Argument[0]" and + output = "ReturnValue" and + preservesValue = false + } + } + + /** A flow summary for frozenset */ + class FrozensetSummary extends SummarizedCallable { + FrozensetSummary() { this = "builtins.frozenset" } + + override DataFlow::CallCfgNode getACall() { result = API::builtin("frozenset").getACall() } + + override DataFlow::ArgumentNode getACallback() { + result = API::builtin("frozenset").getAValueReachableFromSource() + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + any(SetSummary s).propagatesFlowExt(input, output, preservesValue) + } + } + /** A flow summary for `reversed`. */ class ReversedSummary extends SummarizedCallable { ReversedSummary() { this = "builtins.reversed" } diff --git a/python/ql/test/experimental/dataflow/basic/callGraph.ql b/python/ql/test/experimental/dataflow/basic/callGraph.ql index 2e8d6956c70..d83da4c5c11 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraph.ql +++ b/python/ql/test/experimental/dataflow/basic/callGraph.ql @@ -1,5 +1,8 @@ import experimental.dataflow.callGraphConfig from DataFlow::Node source, DataFlow::Node sink -where exists(CallGraphConfig cfg | cfg.hasFlow(source, sink)) +where + exists(CallGraphConfig cfg | cfg.hasFlow(source, sink)) and + exists(source.getLocation().getFile().getRelativePath()) and + exists(sink.getLocation().getFile().getRelativePath()) select source, sink diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected b/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected index ef35d8f5039..e4b8f905530 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected +++ b/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected @@ -1,5 +1,3 @@ -| file://:0:0:0:0 | parameter position 0 of builtins.reversed | -| file://:0:0:0:0 | parameter position 1 of dict.setdefault | | test.py:1:1:1:21 | SynthDictSplatParameterNode | | test.py:1:19:1:19 | ControlFlowNode for x | | test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() | diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql b/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql index 7d15b353274..8b9f57a0462 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql +++ b/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql @@ -1,5 +1,7 @@ import experimental.dataflow.callGraphConfig from DataFlow::Node sink -where exists(CallGraphConfig cfg | cfg.isSink(sink)) +where + exists(CallGraphConfig cfg | cfg.isSink(sink)) and + exists(sink.getLocation().getFile().getRelativePath()) select sink diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSources.expected b/python/ql/test/experimental/dataflow/basic/callGraphSources.expected index 74d546c5f2b..4023ba8f3ea 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSources.expected +++ b/python/ql/test/experimental/dataflow/basic/callGraphSources.expected @@ -1,4 +1,2 @@ -| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | -| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:4:10:4:10 | ControlFlowNode for z | | test.py:7:19:7:19 | ControlFlowNode for a | diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSources.ql b/python/ql/test/experimental/dataflow/basic/callGraphSources.ql index 21c3a5a9ace..e482a07cf39 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSources.ql +++ b/python/ql/test/experimental/dataflow/basic/callGraphSources.ql @@ -1,5 +1,7 @@ import experimental.dataflow.callGraphConfig from DataFlow::Node source -where exists(CallGraphConfig cfg | cfg.isSource(source)) +where + exists(CallGraphConfig cfg | cfg.isSource(source)) and + exists(source.getLocation().getFile().getRelativePath()) select source diff --git a/python/ql/test/experimental/dataflow/basic/global.expected b/python/ql/test/experimental/dataflow/basic/global.expected index 11696c17335..8894bcc190a 100644 --- a/python/ql/test/experimental/dataflow/basic/global.expected +++ b/python/ql/test/experimental/dataflow/basic/global.expected @@ -1,5 +1,3 @@ -| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | | test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | diff --git a/python/ql/test/experimental/dataflow/basic/global.ql b/python/ql/test/experimental/dataflow/basic/global.ql index ba9a302b05b..ecab29899e3 100644 --- a/python/ql/test/experimental/dataflow/basic/global.ql +++ b/python/ql/test/experimental/dataflow/basic/global.ql @@ -3,5 +3,7 @@ import allFlowsConfig from DataFlow::Node source, DataFlow::Node sink where source != sink and - exists(AllFlowsConfig cfg | cfg.hasFlow(source, sink)) + exists(AllFlowsConfig cfg | cfg.hasFlow(source, sink)) and + exists(source.getLocation().getFile().getRelativePath()) and + exists(sink.getLocation().getFile().getRelativePath()) select source, sink diff --git a/python/ql/test/experimental/dataflow/basic/globalStep.expected b/python/ql/test/experimental/dataflow/basic/globalStep.expected index b11ee6fe249..9f228998b9c 100644 --- a/python/ql/test/experimental/dataflow/basic/globalStep.expected +++ b/python/ql/test/experimental/dataflow/basic/globalStep.expected @@ -1,5 +1,3 @@ -| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | diff --git a/python/ql/test/experimental/dataflow/basic/globalStep.ql b/python/ql/test/experimental/dataflow/basic/globalStep.ql index 18014b2cc5f..9b19749b2d8 100644 --- a/python/ql/test/experimental/dataflow/basic/globalStep.ql +++ b/python/ql/test/experimental/dataflow/basic/globalStep.ql @@ -1,5 +1,8 @@ import allFlowsConfig from DataFlow::PathNode fromNode, DataFlow::PathNode toNode -where toNode = fromNode.getASuccessor() +where + toNode = fromNode.getASuccessor() and + exists(fromNode.getNode().getLocation().getFile().getRelativePath()) and + exists(toNode.getNode().getLocation().getFile().getRelativePath()) select fromNode, toNode diff --git a/python/ql/test/experimental/dataflow/basic/local.expected b/python/ql/test/experimental/dataflow/basic/local.expected index 18497a00a60..cdf40018ed0 100644 --- a/python/ql/test/experimental/dataflow/basic/local.expected +++ b/python/ql/test/experimental/dataflow/basic/local.expected @@ -1,11 +1,3 @@ -| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | -| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | -| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | -| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | parameter position 0 of builtins.reversed | file://:0:0:0:0 | parameter position 0 of builtins.reversed | -| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | -| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | parameter position 1 of dict.setdefault | | test.py:0:0:0:0 | GSSA Variable __name__ | test.py:0:0:0:0 | GSSA Variable __name__ | | test.py:0:0:0:0 | GSSA Variable __package__ | test.py:0:0:0:0 | GSSA Variable __package__ | | test.py:0:0:0:0 | GSSA Variable b | test.py:0:0:0:0 | GSSA Variable b | diff --git a/python/ql/test/experimental/dataflow/basic/local.ql b/python/ql/test/experimental/dataflow/basic/local.ql index 5541cea33dc..e13013d2210 100644 --- a/python/ql/test/experimental/dataflow/basic/local.ql +++ b/python/ql/test/experimental/dataflow/basic/local.ql @@ -1,5 +1,8 @@ import semmle.python.dataflow.new.DataFlow from DataFlow::Node fromNode, DataFlow::Node toNode -where DataFlow::localFlow(fromNode, toNode) +where + DataFlow::localFlow(fromNode, toNode) and + exists(fromNode.getLocation().getFile().getRelativePath()) and + exists(toNode.getLocation().getFile().getRelativePath()) select fromNode, toNode diff --git a/python/ql/test/experimental/dataflow/basic/localStep.expected b/python/ql/test/experimental/dataflow/basic/localStep.expected index d05e8aa3a42..e147bb9f4fc 100644 --- a/python/ql/test/experimental/dataflow/basic/localStep.expected +++ b/python/ql/test/experimental/dataflow/basic/localStep.expected @@ -1,5 +1,3 @@ -| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id | | test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id | | test.py:1:19:1:19 | ControlFlowNode for x | test.py:1:19:1:19 | SSA variable x | diff --git a/python/ql/test/experimental/dataflow/basic/localStep.ql b/python/ql/test/experimental/dataflow/basic/localStep.ql index 4e32450f496..37b6bd1a7af 100644 --- a/python/ql/test/experimental/dataflow/basic/localStep.ql +++ b/python/ql/test/experimental/dataflow/basic/localStep.ql @@ -1,5 +1,8 @@ import semmle.python.dataflow.new.DataFlow from DataFlow::Node fromNode, DataFlow::Node toNode -where DataFlow::localFlowStep(fromNode, toNode) +where + DataFlow::localFlowStep(fromNode, toNode) and + exists(fromNode.getLocation().getFile().getRelativePath()) and + exists(toNode.getLocation().getFile().getRelativePath()) select fromNode, toNode diff --git a/python/ql/test/experimental/dataflow/basic/maximalFlows.expected b/python/ql/test/experimental/dataflow/basic/maximalFlows.expected index b65b4b4d30a..b6f8a1730f1 100644 --- a/python/ql/test/experimental/dataflow/basic/maximalFlows.expected +++ b/python/ql/test/experimental/dataflow/basic/maximalFlows.expected @@ -1,4 +1,3 @@ -| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:1:19:1:19 | ControlFlowNode for x | test.py:4:10:4:10 | ControlFlowNode for z | | test.py:1:19:1:19 | ControlFlowNode for x | test.py:7:1:7:1 | GSSA Variable b | | test.py:1:19:1:19 | SSA variable x | test.py:4:10:4:10 | ControlFlowNode for z | diff --git a/python/ql/test/experimental/dataflow/basic/maximalFlows.ql b/python/ql/test/experimental/dataflow/basic/maximalFlows.ql index ddd673954b9..a314cfca612 100644 --- a/python/ql/test/experimental/dataflow/basic/maximalFlows.ql +++ b/python/ql/test/experimental/dataflow/basic/maximalFlows.ql @@ -3,5 +3,7 @@ import maximalFlowsConfig from DataFlow::Node source, DataFlow::Node sink where source != sink and - exists(MaximalFlowsConfig cfg | cfg.hasFlow(source, sink)) + exists(MaximalFlowsConfig cfg | cfg.hasFlow(source, sink)) and + exists(source.getLocation().getFile().getRelativePath()) and + exists(sink.getLocation().getFile().getRelativePath()) select source, sink diff --git a/python/ql/test/experimental/dataflow/basic/sinks.expected b/python/ql/test/experimental/dataflow/basic/sinks.expected index 1e516e32336..944f8190aa5 100644 --- a/python/ql/test/experimental/dataflow/basic/sinks.expected +++ b/python/ql/test/experimental/dataflow/basic/sinks.expected @@ -1,9 +1,3 @@ -| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | -| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | -| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | -| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | parameter position 0 of builtins.reversed | -| file://:0:0:0:0 | parameter position 1 of dict.setdefault | | test.py:0:0:0:0 | GSSA Variable __name__ | | test.py:0:0:0:0 | GSSA Variable __package__ | | test.py:0:0:0:0 | GSSA Variable b | diff --git a/python/ql/test/experimental/dataflow/basic/sinks.ql b/python/ql/test/experimental/dataflow/basic/sinks.ql index 8560bb99d3d..f17ea9b9b1b 100644 --- a/python/ql/test/experimental/dataflow/basic/sinks.ql +++ b/python/ql/test/experimental/dataflow/basic/sinks.ql @@ -1,5 +1,7 @@ import allFlowsConfig from DataFlow::Node sink -where exists(AllFlowsConfig cfg | cfg.isSink(sink)) +where + exists(AllFlowsConfig cfg | cfg.isSink(sink)) and + exists(sink.getLocation().getFile().getRelativePath()) select sink diff --git a/python/ql/test/experimental/dataflow/basic/sources.expected b/python/ql/test/experimental/dataflow/basic/sources.expected index 1e516e32336..944f8190aa5 100644 --- a/python/ql/test/experimental/dataflow/basic/sources.expected +++ b/python/ql/test/experimental/dataflow/basic/sources.expected @@ -1,9 +1,3 @@ -| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | -| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | -| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | -| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | parameter position 0 of builtins.reversed | -| file://:0:0:0:0 | parameter position 1 of dict.setdefault | | test.py:0:0:0:0 | GSSA Variable __name__ | | test.py:0:0:0:0 | GSSA Variable __package__ | | test.py:0:0:0:0 | GSSA Variable b | diff --git a/python/ql/test/experimental/dataflow/basic/sources.ql b/python/ql/test/experimental/dataflow/basic/sources.ql index d079d4db596..198882ceee6 100644 --- a/python/ql/test/experimental/dataflow/basic/sources.ql +++ b/python/ql/test/experimental/dataflow/basic/sources.ql @@ -1,5 +1,7 @@ import allFlowsConfig from DataFlow::Node source -where exists(AllFlowsConfig cfg | cfg.isSource(source)) +where + exists(AllFlowsConfig cfg | cfg.isSource(source)) and + exists(source.getLocation().getFile().getRelativePath()) select source diff --git a/python/ql/test/experimental/dataflow/coverage/test_builtins.py b/python/ql/test/experimental/dataflow/coverage/test_builtins.py index 5d9d92ffcb8..4a3ee95fedf 100644 --- a/python/ql/test/experimental/dataflow/coverage/test_builtins.py +++ b/python/ql/test/experimental/dataflow/coverage/test_builtins.py @@ -41,8 +41,8 @@ def SINK_F(x): def test_list_from_list(): l1 = [SOURCE, NONSOURCE] l2 = list(l1) - SINK(l2[0]) #$ MISSING: flow="SOURCE, l:-2 -> l2[0]" - SINK_F(l2[1]) # expecting FP due to imprecise flow + SINK(l2[0]) #$ flow="SOURCE, l:-2 -> l2[0]" + SINK_F(l2[1]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l2[1]" # -- skip list_from_string @@ -50,13 +50,13 @@ def test_list_from_list(): def test_list_from_tuple(): t = (SOURCE, NONSOURCE) l = list(t) - SINK(l[0]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]" - SINK_F(l[1]) # expecting FP due to imprecise flow + SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]" + SINK_F(l[1]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l[1]" def test_list_from_set(): s = {SOURCE} l = list(s) - SINK(l[0]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]" + SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]" @expects(2) def test_list_from_dict(): @@ -78,7 +78,7 @@ def test_tuple_from_list(): def test_tuple_from_tuple(): t0 = (SOURCE, NONSOURCE) t = tuple(t0) - SINK(t[0]) #$ MISSING: flow="SOURCE, l:-2 -> t[0]" + SINK(t[0]) #$ flow="SOURCE, l:-2 -> t[0]" SINK_F(t[1]) def test_tuple_from_set(): @@ -100,19 +100,19 @@ def test_set_from_list(): l = [SOURCE] s = set(l) v = s.pop() - SINK(v) #$ MISSING: flow="SOURCE, l:-3 -> v" + SINK(v) #$ flow="SOURCE, l:-3 -> v" def test_set_from_tuple(): t = (SOURCE,) s = set(t) v = s.pop() - SINK(v) #$ MISSING: flow="SOURCE, l:-3 -> v" + SINK(v) #$ flow="SOURCE, l:-3 -> v" def test_set_from_set(): s0 = {SOURCE} s = set(s0) v = s.pop() - SINK(v) #$ MISSING: flow="SOURCE, l:-3 -> v" + SINK(v) #$ flow="SOURCE, l:-3 -> v" def test_set_from_dict(): d = {SOURCE: "val"} @@ -126,7 +126,7 @@ def test_set_from_dict(): @expects(2) def test_dict_from_keyword(): d = dict(k = SOURCE, k1 = NONSOURCE) - SINK(d["k"]) #$ MISSING: flow="SOURCE, l:-1 -> d[k]" + SINK(d["k"]) #$ flow="SOURCE, l:-1 -> d['k']" SINK_F(d["k1"]) @expects(2) @@ -139,7 +139,7 @@ def test_dict_from_list(): def test_dict_from_dict(): d1 = {'k': SOURCE, 'k1': NONSOURCE} d2 = dict(d1) - SINK(d2["k"]) #$ MISSING: flow="SOURCE, l:-2 -> d[k]" + SINK(d2["k"]) #$ flow="SOURCE, l:-2 -> d2['k']" SINK_F(d2["k1"]) ## Container methods @@ -278,8 +278,8 @@ def test_reversed_list(): l0 = [SOURCE, NONSOURCE] r = reversed(l0) l = list(r) - SINK_F(l[0]) - SINK(l[1]) #$ MISSING: flow="SOURCE, l:-4 -> l[1]" + SINK_F(l[0]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l[0]" + SINK(l[1]) #$ flow="SOURCE, l:-4 -> l[1]" @expects(2) def test_reversed_tuple(): diff --git a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected index ef6f6a2929b..3b3f18c5b9e 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected @@ -1,5 +1,3 @@ -| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | -| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | | test.py:3:1:3:7 | GSSA Variable tainted | test.py:4:6:4:12 | ControlFlowNode for tainted | | test.py:3:11:3:16 | ControlFlowNode for SOURCE | test.py:3:1:3:7 | GSSA Variable tainted | | test.py:6:1:6:11 | ControlFlowNode for FunctionExpr | test.py:6:5:6:8 | GSSA Variable func | diff --git a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.ql b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.ql index efafa7fec9f..acbb2bea137 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.ql +++ b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.ql @@ -3,5 +3,8 @@ import semmle.python.dataflow.new.TaintTracking import semmle.python.dataflow.new.DataFlow from DataFlow::Node nodeFrom, DataFlow::Node nodeTo -where TaintTracking::localTaintStep(nodeFrom, nodeTo) +where + TaintTracking::localTaintStep(nodeFrom, nodeTo) and + exists(nodeFrom.getLocation().getFile().getRelativePath()) and + exists(nodeTo.getLocation().getFile().getRelativePath()) select nodeFrom, nodeTo diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py index df30a75c3e3..50f9a613f9b 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py @@ -38,8 +38,8 @@ def test_construction(): set(tainted_list), # $ tainted frozenset(tainted_list), # $ tainted dict(tainted_dict), # $ tainted - dict(k = tainted_string)["k"], # $ MISSING: tainted - dict(dict(k = tainted_string))["k"], # $ MISSING: tainted + dict(k = tainted_string)["k"], # $ tainted + dict(dict(k = tainted_string))["k"], # $ tainted dict(["k", tainted_string]), # $ tainted ) diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll index 6a5bc217303..96c015a6a4a 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll @@ -936,10 +936,10 @@ module ExprNodes { } /** A control-flow node that wraps a `StringLiteral` AST expression. */ - class StringLiteralCfgNode extends ExprCfgNode { - override string getAPrimaryQlClass() { result = "StringLiteralCfgNode" } + class StringLiteralCfgNode extends StringlikeLiteralCfgNode { + StringLiteralCfgNode() { e instanceof StringLiteral } - override StringLiteral e; + override string getAPrimaryQlClass() { result = "StringLiteralCfgNode" } final override StringLiteral getExpr() { result = super.getExpr() } } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index 18abb552709..cbdb38d5803 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -940,6 +940,12 @@ private class NewCall extends DataFlowCall { abstract class ReturningNode extends Node { /** Gets the kind of this return node. */ abstract ReturnKind getKind(); + + pragma[nomagic] + predicate hasKind(ReturnKind kind, CfgScope scope) { + kind = this.getKind() and + scope = this.(NodeImpl).getCfgScope() + } } /** A data-flow node that represents a value returned by a callable. */ @@ -1060,10 +1066,8 @@ private module ReturnNodes { SynthReturnNode() { this = TSynthReturnNode(scope, kind) } /** Gets a syntactic return node that flows into this synthetic node. */ - ReturningNode getAnInput() { - result.(NodeImpl).getCfgScope() = scope and - result.getKind() = kind - } + pragma[nomagic] + ReturningNode getAnInput() { result.hasKind(kind, scope) } override ReturnKind getKind() { result = kind } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll index c89a629e198..3381187985a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll @@ -112,6 +112,13 @@ private module Cached { ) } + cached + predicate summaryThroughStepTaint( + DataFlow::Node arg, DataFlow::Node out, FlowSummaryImpl::Public::SummarizedCallable sc + ) { + FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(arg, out, sc) + } + /** * Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local * (intra-procedural) step. @@ -122,7 +129,7 @@ private module Cached { defaultAdditionalTaintStep(nodeFrom, nodeTo) or // Simple flow through library code is included in the exposed local // step relation, even though flow is technically inter-procedural - FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(nodeFrom, nodeTo, _) + summaryThroughStepTaint(nodeFrom, nodeTo, _) } } diff --git a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll index e787ae358e1..d4f8f17db34 100644 --- a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll +++ b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll @@ -21,6 +21,7 @@ private import codeql.ruby.typetracking.TypeTracker private import codeql.ruby.ApiGraphs private import codeql.ruby.Concepts private import codeql.ruby.dataflow.internal.DataFlowPrivate as DataFlowPrivate +private import codeql.ruby.dataflow.internal.TaintTrackingPrivate as TaintTrackingPrivate private import codeql.ruby.TaintTracking private import codeql.ruby.frameworks.core.String @@ -37,43 +38,6 @@ DataFlow::LocalSourceNode strStart() { /** Gets a dataflow node for a regular expression literal. */ DataFlow::LocalSourceNode regStart() { result.asExpr().getExpr() instanceof Ast::RegExpLiteral } -/** - * Holds if the analysis should track flow from `nodeFrom` to `nodeTo` on top of the ordinary type-tracking steps. - * `nodeFrom` and `nodeTo` has type `fromType` and `toType` respectively. - * The types are either "string" or "regexp". - */ -predicate step( - DataFlow::Node nodeFrom, DataFlow::LocalSourceNode nodeTo, string fromType, string toType -) { - fromType = toType and - fromType = "string" and - ( - // include taint flow through `String` summaries - TaintTracking::localTaintStep(nodeFrom, nodeTo) and - nodeFrom.(DataFlowPrivate::SummaryNode).getSummarizedCallable() instanceof - String::SummarizedCallable - or - // string concatenations, and - exists(CfgNodes::ExprNodes::OperationCfgNode op | - op = nodeTo.asExpr() and - op.getAnOperand() = nodeFrom.asExpr() and - op.getExpr().(Ast::BinaryOperation).getOperator() = "+" - ) - or - // string interpolations - nodeFrom.asExpr() = - nodeTo.asExpr().(CfgNodes::ExprNodes::StringlikeLiteralCfgNode).getAComponent() - ) - or - fromType = "string" and - toType = "reg" and - exists(DataFlow::CallNode call | - call = API::getTopLevelMember("Regexp").getAMethodCall(["compile", "new"]) and - nodeFrom = call.getArgument(0) and - nodeTo = call - ) -} - /** Gets a node where string values that flow to the node are interpreted as regular expressions. */ DataFlow::Node stringSink() { result instanceof RE::RegExpInterpretation::Range and @@ -91,28 +55,139 @@ DataFlow::Node stringSink() { /** Gets a node where regular expressions that flow to the node are used. */ DataFlow::Node regSink() { result = any(RegexExecution exec).getRegex() } -/** Gets a node that is reachable by type-tracking from any string or regular expression. */ -DataFlow::LocalSourceNode forward(TypeTracker t) { - t.start() and - result = [strStart(), regStart()] - or - exists(TypeTracker t2 | result = forward(t2).track(t2, t)) - or - exists(TypeTracker t2 | t2 = t.continue() | step(forward(t2).getALocalUse(), result, _, _)) +private signature module TypeTrackInputSig { + DataFlow::LocalSourceNode start(TypeTracker t, DataFlow::Node start); + + predicate end(DataFlow::Node n); + + predicate additionalStep(DataFlow::Node nodeFrom, DataFlow::LocalSourceNode nodeTo); } /** - * Gets a node that is backwards reachable from any regular expression use, - * where that use is reachable by type-tracking from any string or regular expression. + * Provides a version of type tracking where we first prune for reachable nodes, + * before doing the type tracking computation. */ -DataFlow::LocalSourceNode backwards(TypeBackTracker t) { - t.start() and - result.flowsTo([stringSink(), regSink()]) and - result = forward(TypeTracker::end()) - or - exists(TypeBackTracker t2 | result = backwards(t2).backtrack(t2, t)) - or - exists(TypeBackTracker t2 | t2 = t.continue() | step(result.getALocalUse(), backwards(t2), _, _)) +private module TypeTrack { + private predicate additionalStep( + DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo + ) { + Input::additionalStep(nodeFrom.getALocalUse(), nodeTo) + } + + /** Gets a node that is forwards reachable by type-tracking. */ + pragma[nomagic] + private DataFlow::LocalSourceNode forward(TypeTracker t) { + result = Input::start(t, _) + or + exists(TypeTracker t2 | result = forward(t2).track(t2, t)) + or + exists(TypeTracker t2 | t2 = t.continue() | additionalStep(forward(t2), result)) + } + + bindingset[result, tbt] + pragma[inline_late] + pragma[noopt] + private DataFlow::LocalSourceNode forwardLateInline(TypeBackTracker tbt) { + exists(TypeTracker tt | + result = forward(tt) and + tt = tbt.getACompatibleTypeTracker() + ) + } + + /** Gets a node that is backwards reachable by type-tracking. */ + pragma[nomagic] + private DataFlow::LocalSourceNode backwards(TypeBackTracker t) { + result = forwardLateInline(t) and + ( + t.start() and + Input::end(result.getALocalUse()) + or + exists(TypeBackTracker t2 | result = backwards(t2).backtrack(t2, t)) + or + exists(TypeBackTracker t2 | t2 = t.continue() | additionalStep(result, backwards(t2))) + ) + } + + bindingset[result, tt] + pragma[inline_late] + pragma[noopt] + private DataFlow::LocalSourceNode backwardsInlineLate(TypeTracker tt) { + exists(TypeBackTracker tbt | + result = backwards(tbt) and + tt = tbt.getACompatibleTypeTracker() + ) + } + + /** Holds if `n` is forwards and backwards reachable with type tracker `t`. */ + pragma[nomagic] + private predicate reached(DataFlow::LocalSourceNode n, TypeTracker t) { + n = forward(t) and + n = backwardsInlineLate(t) + } + + pragma[nomagic] + private TypeTracker stepReached( + TypeTracker t, DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo + ) { + exists(StepSummary summary | + StepSummary::step(nodeFrom, nodeTo, summary) and + reached(nodeFrom, t) and + reached(nodeTo, result) and + result = t.append(summary) + ) + or + additionalStep(nodeFrom, nodeTo) and + reached(nodeFrom, pragma[only_bind_into](t)) and + reached(nodeTo, pragma[only_bind_into](t)) and + result = t.continue() + } + + /** Gets a node that has been tracked from the start node `start`. */ + DataFlow::LocalSourceNode track(DataFlow::Node start, TypeTracker t) { + t.start() and + result = Input::start(t, start) and + reached(result, t) + or + exists(TypeTracker t2 | t = stepReached(t2, track(start, t2), result)) + } +} + +/** Holds if `inputStr` is compiled to a regular expression that is returned at `call`. */ +pragma[nomagic] +private predicate regFromString(DataFlow::LocalSourceNode inputStr, DataFlow::CallNode call) { + exists(DataFlow::Node mid | + inputStr.flowsTo(mid) and + call = API::getTopLevelMember("Regexp").getAMethodCall(["compile", "new"]) and + mid = call.getArgument(0) + ) +} + +private module StringTypeTrackInput implements TypeTrackInputSig { + DataFlow::LocalSourceNode start(TypeTracker t, DataFlow::Node start) { + start = strStart() and t.start() and result = start + } + + predicate end(DataFlow::Node n) { + n = stringSink() or + regFromString(n, _) + } + + predicate additionalStep(DataFlow::Node nodeFrom, DataFlow::LocalSourceNode nodeTo) { + // include taint flow through `String` summaries + TaintTrackingPrivate::summaryThroughStepTaint(nodeFrom, nodeTo, + any(String::SummarizedCallable c)) + or + // string concatenations, and + exists(CfgNodes::ExprNodes::OperationCfgNode op | + op = nodeTo.asExpr() and + op.getAnOperand() = nodeFrom.asExpr() and + op.getExpr().(Ast::BinaryOperation).getOperator() = "+" + ) + or + // string interpolations + nodeFrom.asExpr() = + nodeTo.asExpr().(CfgNodes::ExprNodes::StringlikeLiteralCfgNode).getAComponent() + } } /** @@ -120,41 +195,34 @@ DataFlow::LocalSourceNode backwards(TypeBackTracker t) { * This is used to figure out where `start` is evaluated as a regular expression against an input string, * or where `start` is compiled into a regular expression. */ -private DataFlow::LocalSourceNode trackStrings(DataFlow::Node start, TypeTracker t) { - result = backwards(_) and - ( +private predicate trackStrings = TypeTrack::track/2; + +/** Holds if `strConst` flows to a regex compilation (tracked by `t`), where the resulting regular expression is stored in `reg`. */ +pragma[nomagic] +private predicate regFromStringStart(DataFlow::Node strConst, TypeTracker t, DataFlow::CallNode reg) { + regFromString(trackStrings(strConst, t), reg) and + exists(t.continue()) +} + +private module RegTypeTrackInput implements TypeTrackInputSig { + DataFlow::LocalSourceNode start(TypeTracker t, DataFlow::Node start) { + start = regStart() and t.start() and - start = result and - result = strStart() + result = start or - exists(TypeTracker t2 | result = trackStrings(start, t2).track(t2, t)) - or - // an additional step from string to string - exists(TypeTracker t2 | t2 = t.continue() | - step(trackStrings(start, t2).getALocalUse(), result, "string", "string") - ) - ) + regFromStringStart(start, t, result) + } + + predicate end(DataFlow::Node n) { n = regSink() } + + predicate additionalStep(DataFlow::Node nodeFrom, DataFlow::LocalSourceNode nodeTo) { none() } } /** * Gets a node that has been tracked from the regular expression `start` to some node. * This is used to figure out where `start` is executed against an input string. */ -private DataFlow::LocalSourceNode trackRegs(DataFlow::Node start, TypeTracker t) { - result = backwards(_) and - ( - t.start() and - start = result and - result = regStart() - or - exists(TypeTracker t2 | result = trackRegs(start, t2).track(t2, t)) - or - // an additional step where a string is converted to a regular expression - exists(TypeTracker t2 | t2 = t.continue() | - step(trackStrings(start, t2).getALocalUse(), result, "string", "reg") - ) - ) -} +private predicate trackRegs = TypeTrack::track/2; /** Gets a node that references a regular expression. */ private DataFlow::LocalSourceNode trackRegexpType(TypeTracker t) { diff --git a/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll b/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll index 52807799c2c..d4d9e1f31f5 100644 --- a/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll +++ b/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll @@ -613,8 +613,17 @@ class TypeBackTracker extends TTypeBackTracker { * also flow to `sink`. */ TypeTracker getACompatibleTypeTracker() { - exists(boolean hasCall | result = MkTypeTracker(hasCall, content) | - hasCall = false or this.hasReturn() = false + exists(boolean hasCall, OptionalTypeTrackerContent c | + result = MkTypeTracker(hasCall, c) and + ( + compatibleContents(c, content) + or + content = noContent() and c = content + ) + | + hasCall = false + or + this.hasReturn() = false ) } } diff --git a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll index 69ac88c777e..7402b9ea18e 100644 --- a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll @@ -80,10 +80,8 @@ predicate jumpStep = DataFlowPrivate::jumpStep/2; pragma[nomagic] private predicate flowThrough(DataFlowPublic::ParameterNode param) { exists(DataFlowPrivate::ReturningNode returnNode, DataFlowDispatch::ReturnKind rk | - DataFlowPrivate::LocalFlow::getParameterDefNode(param.getParameter()) - .(TypeTrackingNode) - .flowsTo(returnNode) and - rk = returnNode.getKind() + param.flowsTo(returnNode) and + returnNode.hasKind(rk, param.(DataFlowPrivate::NodeImpl).getCfgScope()) | rk instanceof DataFlowDispatch::NormalReturnKind or diff --git a/ruby/ql/test/library-tests/modules/ancestors.expected b/ruby/ql/test/library-tests/modules/ancestors.expected index 2ebc068459f..042808a34f0 100644 --- a/ruby/ql/test/library-tests/modules/ancestors.expected +++ b/ruby/ql/test/library-tests/modules/ancestors.expected @@ -94,64 +94,64 @@ calls.rb: # 325| C1 #-----| super -> Object -# 331| C2 +# 335| C2 #-----| super -> C1 -# 337| C3 +# 341| C3 #-----| super -> C2 -# 377| SingletonOverride1 +# 385| SingletonOverride1 #-----| super -> Object -# 412| SingletonOverride2 +# 420| SingletonOverride2 #-----| super -> SingletonOverride1 -# 433| ConditionalInstanceMethods +# 441| ConditionalInstanceMethods #-----| super -> Object -# 496| ExtendSingletonMethod +# 504| ExtendSingletonMethod -# 506| ExtendSingletonMethod2 +# 514| ExtendSingletonMethod2 -# 512| ExtendSingletonMethod3 +# 520| ExtendSingletonMethod3 -# 525| ProtectedMethodInModule +# 533| ProtectedMethodInModule -# 531| ProtectedMethods +# 539| ProtectedMethods #-----| super -> Object #-----| include -> ProtectedMethodInModule -# 550| ProtectedMethodsSub +# 558| ProtectedMethodsSub #-----| super -> ProtectedMethods -# 564| SingletonUpCall_Base +# 572| SingletonUpCall_Base #-----| super -> Object -# 568| SingletonUpCall_Sub +# 576| SingletonUpCall_Sub #-----| super -> SingletonUpCall_Base -# 576| SingletonUpCall_SubSub +# 584| SingletonUpCall_SubSub #-----| super -> SingletonUpCall_Sub -# 583| SingletonA +# 591| SingletonA #-----| super -> Object -# 596| SingletonB +# 604| SingletonB #-----| super -> SingletonA -# 605| SingletonC +# 613| SingletonC #-----| super -> SingletonA -# 618| Included +# 626| Included -# 626| IncludesIncluded +# 634| IncludesIncluded #-----| super -> Object #-----| include -> Included -# 633| CustomNew1 +# 641| CustomNew1 #-----| super -> Object -# 641| CustomNew2 +# 649| CustomNew2 #-----| super -> Object hello.rb: diff --git a/ruby/ql/test/library-tests/modules/callgraph.expected b/ruby/ql/test/library-tests/modules/callgraph.expected index d888b8b2474..cadc31e6940 100644 --- a/ruby/ql/test/library-tests/modules/callgraph.expected +++ b/ruby/ql/test/library-tests/modules/callgraph.expected @@ -117,134 +117,146 @@ getTarget | calls.rb:320:5:320:16 | call to instance | calls.rb:311:5:314:7 | instance | | calls.rb:323:1:323:17 | call to singleton | calls.rb:316:5:318:7 | singleton | | calls.rb:327:9:327:26 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:333:9:333:26 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:339:9:339:26 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:346:9:346:18 | call to instance | calls.rb:338:5:340:7 | instance | -| calls.rb:348:9:348:18 | call to instance | calls.rb:332:5:334:7 | instance | -| calls.rb:348:9:348:18 | call to instance | calls.rb:338:5:340:7 | instance | -| calls.rb:350:9:350:18 | call to instance | calls.rb:326:5:328:7 | instance | -| calls.rb:350:9:350:18 | call to instance | calls.rb:332:5:334:7 | instance | -| calls.rb:350:9:350:18 | call to instance | calls.rb:338:5:340:7 | instance | -| calls.rb:355:20:355:29 | call to instance | calls.rb:338:5:340:7 | instance | -| calls.rb:356:26:356:36 | call to instance | calls.rb:332:5:334:7 | instance | -| calls.rb:356:26:356:36 | call to instance | calls.rb:338:5:340:7 | instance | -| calls.rb:357:26:357:36 | call to instance | calls.rb:326:5:328:7 | instance | -| calls.rb:357:26:357:36 | call to instance | calls.rb:332:5:334:7 | instance | -| calls.rb:357:26:357:36 | call to instance | calls.rb:338:5:340:7 | instance | -| calls.rb:361:6:361:11 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:362:1:362:11 | call to instance | calls.rb:326:5:328:7 | instance | -| calls.rb:363:1:363:25 | call to pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:363:19:363:24 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:364:1:364:25 | call to pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:364:19:364:24 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:365:1:365:25 | call to pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:365:19:365:24 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:369:9:369:28 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:373:6:373:11 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:374:1:374:16 | call to add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:375:1:375:11 | call to instance | calls.rb:326:5:328:7 | instance | -| calls.rb:375:1:375:11 | call to instance | calls.rb:368:5:370:7 | instance | -| calls.rb:380:13:380:48 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:379:9:381:11 | singleton1 | -| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:414:9:416:11 | singleton1 | -| calls.rb:388:13:388:20 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:388:13:388:30 | call to instance1 | calls.rb:402:5:404:7 | instance1 | -| calls.rb:388:13:388:30 | call to instance1 | calls.rb:423:5:425:7 | instance1 | -| calls.rb:393:9:393:44 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:397:9:397:18 | call to singleton2 | calls.rb:392:5:394:7 | singleton2 | -| calls.rb:397:9:397:18 | call to singleton2 | calls.rb:419:5:421:7 | singleton2 | -| calls.rb:400:5:400:14 | call to singleton2 | calls.rb:392:5:394:7 | singleton2 | -| calls.rb:403:9:403:43 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:407:1:407:29 | call to singleton1 | calls.rb:379:9:381:11 | singleton1 | -| calls.rb:408:1:408:29 | call to singleton2 | calls.rb:392:5:394:7 | singleton2 | -| calls.rb:409:1:409:34 | call to call_singleton1 | calls.rb:383:9:385:11 | call_singleton1 | -| calls.rb:410:1:410:34 | call to call_singleton2 | calls.rb:396:5:398:7 | call_singleton2 | -| calls.rb:415:13:415:48 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:420:9:420:44 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:424:9:424:43 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:428:1:428:29 | call to singleton1 | calls.rb:414:9:416:11 | singleton1 | -| calls.rb:429:1:429:29 | call to singleton2 | calls.rb:419:5:421:7 | singleton2 | -| calls.rb:430:1:430:34 | call to call_singleton1 | calls.rb:383:9:385:11 | call_singleton1 | -| calls.rb:431:1:431:34 | call to call_singleton2 | calls.rb:396:5:398:7 | call_singleton2 | -| calls.rb:436:13:436:48 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:441:9:441:44 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:337:9:337:26 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:343:9:343:26 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:350:9:350:18 | call to instance | calls.rb:342:5:344:7 | instance | +| calls.rb:352:9:352:18 | call to instance | calls.rb:336:5:338:7 | instance | +| calls.rb:352:9:352:18 | call to instance | calls.rb:342:5:344:7 | instance | +| calls.rb:354:9:354:18 | call to instance | calls.rb:326:5:328:7 | instance | +| calls.rb:354:9:354:18 | call to instance | calls.rb:336:5:338:7 | instance | +| calls.rb:354:9:354:18 | call to instance | calls.rb:342:5:344:7 | instance | +| calls.rb:359:20:359:29 | call to instance | calls.rb:342:5:344:7 | instance | +| calls.rb:360:26:360:36 | call to instance | calls.rb:336:5:338:7 | instance | +| calls.rb:360:26:360:36 | call to instance | calls.rb:342:5:344:7 | instance | +| calls.rb:361:26:361:36 | call to instance | calls.rb:326:5:328:7 | instance | +| calls.rb:361:26:361:36 | call to instance | calls.rb:336:5:338:7 | instance | +| calls.rb:361:26:361:36 | call to instance | calls.rb:342:5:344:7 | instance | +| calls.rb:365:6:365:11 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:366:1:366:11 | call to instance | calls.rb:326:5:328:7 | instance | +| calls.rb:368:1:368:25 | call to pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:368:19:368:24 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:369:1:369:25 | call to pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:369:19:369:24 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:370:1:370:25 | call to pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:370:19:370:24 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:372:1:372:6 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:372:1:372:18 | call to return_self | calls.rb:330:5:332:7 | return_self | +| calls.rb:372:1:372:27 | call to instance | calls.rb:326:5:328:7 | instance | +| calls.rb:372:1:372:27 | call to instance | calls.rb:336:5:338:7 | instance | +| calls.rb:372:1:372:27 | call to instance | calls.rb:342:5:344:7 | instance | +| calls.rb:376:9:376:28 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:380:6:380:11 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:381:1:381:16 | call to add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:382:1:382:11 | call to instance | calls.rb:326:5:328:7 | instance | +| calls.rb:382:1:382:11 | call to instance | calls.rb:375:5:377:7 | instance | +| calls.rb:383:1:383:14 | call to return_self | calls.rb:330:5:332:7 | return_self | +| calls.rb:383:1:383:23 | call to instance | calls.rb:326:5:328:7 | instance | +| calls.rb:383:1:383:23 | call to instance | calls.rb:336:5:338:7 | instance | +| calls.rb:383:1:383:23 | call to instance | calls.rb:342:5:344:7 | instance | +| calls.rb:383:1:383:23 | call to instance | calls.rb:375:5:377:7 | instance | +| calls.rb:388:13:388:48 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:387:9:389:11 | singleton1 | +| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:422:9:424:11 | singleton1 | +| calls.rb:396:13:396:20 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:396:13:396:30 | call to instance1 | calls.rb:410:5:412:7 | instance1 | +| calls.rb:396:13:396:30 | call to instance1 | calls.rb:431:5:433:7 | instance1 | +| calls.rb:401:9:401:44 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:405:9:405:18 | call to singleton2 | calls.rb:400:5:402:7 | singleton2 | +| calls.rb:405:9:405:18 | call to singleton2 | calls.rb:427:5:429:7 | singleton2 | +| calls.rb:408:5:408:14 | call to singleton2 | calls.rb:400:5:402:7 | singleton2 | +| calls.rb:411:9:411:43 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:415:1:415:29 | call to singleton1 | calls.rb:387:9:389:11 | singleton1 | +| calls.rb:416:1:416:29 | call to singleton2 | calls.rb:400:5:402:7 | singleton2 | +| calls.rb:417:1:417:34 | call to call_singleton1 | calls.rb:391:9:393:11 | call_singleton1 | +| calls.rb:418:1:418:34 | call to call_singleton2 | calls.rb:404:5:406:7 | call_singleton2 | +| calls.rb:423:13:423:48 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:428:9:428:44 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:432:9:432:43 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:436:1:436:29 | call to singleton1 | calls.rb:422:9:424:11 | singleton1 | +| calls.rb:437:1:437:29 | call to singleton2 | calls.rb:427:5:429:7 | singleton2 | +| calls.rb:438:1:438:34 | call to call_singleton1 | calls.rb:391:9:393:11 | call_singleton1 | +| calls.rb:439:1:439:34 | call to call_singleton2 | calls.rb:404:5:406:7 | call_singleton2 | | calls.rb:444:13:444:48 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:447:17:447:52 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:455:9:459:11 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:455:9:459:15 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:457:17:457:40 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:463:1:463:30 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:463:1:463:33 | call to m1 | calls.rb:435:9:437:11 | m1 | -| calls.rb:464:1:464:30 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:465:1:465:30 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:465:1:465:33 | call to m2 | calls.rb:440:5:452:7 | m2 | -| calls.rb:466:1:466:30 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:467:1:467:30 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:468:1:468:30 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:470:27:488:3 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:473:13:473:22 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:477:5:481:7 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:477:5:481:11 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:479:13:479:22 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:485:13:485:27 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:490:1:490:27 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:491:1:491:27 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:492:1:492:27 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:493:1:493:27 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:494:1:494:27 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:504:1:504:31 | call to singleton | calls.rb:497:5:499:7 | singleton | -| calls.rb:510:1:510:32 | call to singleton | calls.rb:497:5:499:7 | singleton | -| calls.rb:517:1:517:32 | call to singleton | calls.rb:497:5:499:7 | singleton | -| calls.rb:523:1:523:13 | call to singleton | calls.rb:497:5:499:7 | singleton | -| calls.rb:532:5:532:35 | call to include | calls.rb:108:5:110:7 | include | -| calls.rb:535:9:535:35 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:539:9:539:11 | call to foo | calls.rb:526:15:528:7 | foo | -| calls.rb:540:9:540:11 | call to bar | calls.rb:534:15:536:7 | bar | -| calls.rb:541:9:541:28 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:541:9:541:32 | call to foo | calls.rb:526:15:528:7 | foo | -| calls.rb:542:9:542:28 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:542:9:542:32 | call to bar | calls.rb:534:15:536:7 | bar | -| calls.rb:546:1:546:20 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:547:1:547:20 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:548:1:548:20 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:548:1:548:24 | call to baz | calls.rb:538:5:543:7 | baz | -| calls.rb:552:9:552:11 | call to foo | calls.rb:526:15:528:7 | foo | -| calls.rb:553:9:553:31 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:553:9:553:35 | call to foo | calls.rb:526:15:528:7 | foo | -| calls.rb:557:1:557:23 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:558:1:558:23 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:559:1:559:23 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:559:1:559:27 | call to baz | calls.rb:551:5:554:7 | baz | -| calls.rb:561:2:561:6 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:561:20:561:24 | call to baz | calls.rb:51:5:57:7 | baz | -| calls.rb:562:26:562:37 | call to capitalize | calls.rb:97:5:97:23 | capitalize | -| calls.rb:569:5:569:13 | call to singleton | calls.rb:565:5:566:7 | singleton | -| calls.rb:572:9:572:17 | call to singleton | calls.rb:565:5:566:7 | singleton | -| calls.rb:573:9:573:18 | call to singleton2 | calls.rb:577:5:578:7 | singleton2 | -| calls.rb:580:5:580:14 | call to mid_method | calls.rb:571:5:574:7 | mid_method | -| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:584:5:585:7 | singleton1 | -| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:597:5:598:7 | singleton1 | -| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:606:5:607:7 | singleton1 | -| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:587:5:589:7 | call_singleton1 | -| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:600:5:602:7 | call_singleton1 | -| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:609:5:611:7 | call_singleton1 | -| calls.rb:601:9:601:18 | call to singleton1 | calls.rb:597:5:598:7 | singleton1 | -| calls.rb:610:9:610:18 | call to singleton1 | calls.rb:606:5:607:7 | singleton1 | -| calls.rb:614:1:614:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 | -| calls.rb:615:1:615:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 | -| calls.rb:616:1:616:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 | -| calls.rb:620:9:620:16 | call to bar | calls.rb:622:5:623:7 | bar | -| calls.rb:620:9:620:16 | call to bar | calls.rb:628:5:630:7 | bar | -| calls.rb:627:5:627:20 | call to include | calls.rb:108:5:110:7 | include | -| calls.rb:629:9:629:13 | super call to bar | calls.rb:622:5:623:7 | bar | -| calls.rb:635:9:635:14 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:639:1:639:14 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:639:1:639:14 | call to new | calls.rb:634:5:636:7 | new | -| calls.rb:639:1:639:23 | call to instance | calls.rb:326:5:328:7 | instance | -| calls.rb:647:9:647:34 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:651:1:651:14 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:651:1:651:14 | call to new | calls.rb:642:5:644:7 | new | -| calls.rb:651:1:651:23 | call to instance | calls.rb:646:5:648:7 | instance | +| calls.rb:449:9:449:44 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:452:13:452:48 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:455:17:455:52 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:463:9:467:11 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:463:9:467:15 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:465:17:465:40 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:471:1:471:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:471:1:471:33 | call to m1 | calls.rb:443:9:445:11 | m1 | +| calls.rb:472:1:472:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:473:1:473:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:473:1:473:33 | call to m2 | calls.rb:448:5:460:7 | m2 | +| calls.rb:474:1:474:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:475:1:475:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:476:1:476:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:478:27:496:3 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:481:13:481:22 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:485:5:489:7 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:485:5:489:11 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:487:13:487:22 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:493:13:493:27 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:498:1:498:27 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:499:1:499:27 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:500:1:500:27 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:501:1:501:27 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:502:1:502:27 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:512:1:512:31 | call to singleton | calls.rb:505:5:507:7 | singleton | +| calls.rb:518:1:518:32 | call to singleton | calls.rb:505:5:507:7 | singleton | +| calls.rb:525:1:525:32 | call to singleton | calls.rb:505:5:507:7 | singleton | +| calls.rb:531:1:531:13 | call to singleton | calls.rb:505:5:507:7 | singleton | +| calls.rb:540:5:540:35 | call to include | calls.rb:108:5:110:7 | include | +| calls.rb:543:9:543:35 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:547:9:547:11 | call to foo | calls.rb:534:15:536:7 | foo | +| calls.rb:548:9:548:11 | call to bar | calls.rb:542:15:544:7 | bar | +| calls.rb:549:9:549:28 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:549:9:549:32 | call to foo | calls.rb:534:15:536:7 | foo | +| calls.rb:550:9:550:28 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:550:9:550:32 | call to bar | calls.rb:542:15:544:7 | bar | +| calls.rb:554:1:554:20 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:555:1:555:20 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:556:1:556:20 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:556:1:556:24 | call to baz | calls.rb:546:5:551:7 | baz | +| calls.rb:560:9:560:11 | call to foo | calls.rb:534:15:536:7 | foo | +| calls.rb:561:9:561:31 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:561:9:561:35 | call to foo | calls.rb:534:15:536:7 | foo | +| calls.rb:565:1:565:23 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:566:1:566:23 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:567:1:567:23 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:567:1:567:27 | call to baz | calls.rb:559:5:562:7 | baz | +| calls.rb:569:2:569:6 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:569:20:569:24 | call to baz | calls.rb:51:5:57:7 | baz | +| calls.rb:570:26:570:37 | call to capitalize | calls.rb:97:5:97:23 | capitalize | +| calls.rb:577:5:577:13 | call to singleton | calls.rb:573:5:574:7 | singleton | +| calls.rb:580:9:580:17 | call to singleton | calls.rb:573:5:574:7 | singleton | +| calls.rb:581:9:581:18 | call to singleton2 | calls.rb:585:5:586:7 | singleton2 | +| calls.rb:588:5:588:14 | call to mid_method | calls.rb:579:5:582:7 | mid_method | +| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:592:5:593:7 | singleton1 | +| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:605:5:606:7 | singleton1 | +| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:614:5:615:7 | singleton1 | +| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:595:5:597:7 | call_singleton1 | +| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:608:5:610:7 | call_singleton1 | +| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:617:5:619:7 | call_singleton1 | +| calls.rb:609:9:609:18 | call to singleton1 | calls.rb:605:5:606:7 | singleton1 | +| calls.rb:618:9:618:18 | call to singleton1 | calls.rb:614:5:615:7 | singleton1 | +| calls.rb:622:1:622:31 | call to call_call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 | +| calls.rb:623:1:623:31 | call to call_call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 | +| calls.rb:624:1:624:31 | call to call_call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 | +| calls.rb:628:9:628:16 | call to bar | calls.rb:630:5:631:7 | bar | +| calls.rb:628:9:628:16 | call to bar | calls.rb:636:5:638:7 | bar | +| calls.rb:635:5:635:20 | call to include | calls.rb:108:5:110:7 | include | +| calls.rb:637:9:637:13 | super call to bar | calls.rb:630:5:631:7 | bar | +| calls.rb:643:9:643:14 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:647:1:647:14 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:647:1:647:14 | call to new | calls.rb:642:5:644:7 | new | +| calls.rb:647:1:647:23 | call to instance | calls.rb:326:5:328:7 | instance | +| calls.rb:655:9:655:34 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:659:1:659:14 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:659:1:659:14 | call to new | calls.rb:650:5:652:7 | new | +| calls.rb:659:1:659:23 | call to instance | calls.rb:654:5:656:7 | instance | +| calls.rb:667:2:667:25 | call to capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:667:20:667:25 | call to new | calls.rb:117:5:117:16 | new | | hello.rb:12:5:12:24 | call to include | calls.rb:108:5:110:7 | include | | hello.rb:14:16:14:20 | call to hello | hello.rb:2:5:4:7 | hello | | hello.rb:20:16:20:20 | super call to message | hello.rb:13:5:15:7 | message | @@ -330,46 +342,49 @@ unresolvedCall | calls.rb:274:1:274:14 | call to singleton_g | | calls.rb:276:1:276:14 | call to singleton_g | | calls.rb:313:9:313:20 | call to instance | -| calls.rb:434:8:434:13 | call to rand | -| calls.rb:434:8:434:17 | ... > ... | -| calls.rb:451:9:451:10 | call to m3 | -| calls.rb:454:8:454:13 | call to rand | -| calls.rb:454:8:454:17 | ... > ... | -| calls.rb:455:9:459:18 | call to m5 | -| calls.rb:464:1:464:33 | call to m3 | -| calls.rb:466:1:466:33 | call to m3 | -| calls.rb:467:1:467:33 | call to m4 | -| calls.rb:468:1:468:33 | call to m5 | -| calls.rb:471:5:471:11 | call to [] | -| calls.rb:471:5:475:7 | call to each | -| calls.rb:477:5:481:15 | call to bar | -| calls.rb:483:5:483:11 | call to [] | -| calls.rb:483:5:487:7 | call to each | -| calls.rb:484:9:486:11 | call to define_method | -| calls.rb:490:1:490:31 | call to foo | -| calls.rb:491:1:491:31 | call to bar | -| calls.rb:492:1:492:33 | call to baz_0 | -| calls.rb:493:1:493:33 | call to baz_1 | -| calls.rb:494:1:494:33 | call to baz_2 | -| calls.rb:498:9:498:46 | call to puts | -| calls.rb:501:5:501:15 | call to extend | -| calls.rb:507:5:507:32 | call to extend | -| calls.rb:515:1:515:51 | call to extend | -| calls.rb:520:1:520:13 | call to singleton | -| calls.rb:521:1:521:32 | call to extend | -| calls.rb:526:5:528:7 | call to protected | -| calls.rb:527:9:527:42 | call to puts | +| calls.rb:442:8:442:13 | call to rand | +| calls.rb:442:8:442:17 | ... > ... | +| calls.rb:459:9:459:10 | call to m3 | +| calls.rb:462:8:462:13 | call to rand | +| calls.rb:462:8:462:17 | ... > ... | +| calls.rb:463:9:467:18 | call to m5 | +| calls.rb:472:1:472:33 | call to m3 | +| calls.rb:474:1:474:33 | call to m3 | +| calls.rb:475:1:475:33 | call to m4 | +| calls.rb:476:1:476:33 | call to m5 | +| calls.rb:479:5:479:11 | call to [] | +| calls.rb:479:5:483:7 | call to each | +| calls.rb:485:5:489:15 | call to bar | +| calls.rb:491:5:491:11 | call to [] | +| calls.rb:491:5:495:7 | call to each | +| calls.rb:492:9:494:11 | call to define_method | +| calls.rb:498:1:498:31 | call to foo | +| calls.rb:499:1:499:31 | call to bar | +| calls.rb:500:1:500:33 | call to baz_0 | +| calls.rb:501:1:501:33 | call to baz_1 | +| calls.rb:502:1:502:33 | call to baz_2 | +| calls.rb:506:9:506:46 | call to puts | +| calls.rb:509:5:509:15 | call to extend | +| calls.rb:515:5:515:32 | call to extend | +| calls.rb:523:1:523:51 | call to extend | +| calls.rb:528:1:528:13 | call to singleton | +| calls.rb:529:1:529:32 | call to extend | | calls.rb:534:5:536:7 | call to protected | -| calls.rb:546:1:546:24 | call to foo | -| calls.rb:547:1:547:24 | call to bar | -| calls.rb:557:1:557:27 | call to foo | -| calls.rb:558:1:558:27 | call to bar | -| calls.rb:561:1:561:7 | call to [] | -| calls.rb:561:1:561:26 | call to each | -| calls.rb:562:1:562:13 | call to [] | -| calls.rb:562:1:562:39 | call to each | -| calls.rb:570:5:570:14 | call to singleton2 | -| calls.rb:643:9:643:21 | call to allocate | +| calls.rb:535:9:535:42 | call to puts | +| calls.rb:542:5:544:7 | call to protected | +| calls.rb:554:1:554:24 | call to foo | +| calls.rb:555:1:555:24 | call to bar | +| calls.rb:565:1:565:27 | call to foo | +| calls.rb:566:1:566:27 | call to bar | +| calls.rb:569:1:569:7 | call to [] | +| calls.rb:569:1:569:26 | call to each | +| calls.rb:570:1:570:13 | call to [] | +| calls.rb:570:1:570:39 | call to each | +| calls.rb:578:5:578:14 | call to singleton2 | +| calls.rb:651:9:651:21 | call to allocate | +| calls.rb:662:5:662:11 | call to [] | +| calls.rb:662:5:664:7 | call to each | +| calls.rb:667:1:667:35 | call to instance | | hello.rb:20:16:20:26 | ... + ... | | hello.rb:20:16:20:34 | ... + ... | | hello.rb:20:16:20:40 | ... + ... | @@ -397,10 +412,11 @@ privateMethod | calls.rb:158:1:160:3 | indirect | | calls.rb:185:1:186:3 | private_on_main | | calls.rb:278:1:286:3 | create | -| calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:367:1:371:3 | add_singleton | -| calls.rb:472:9:474:11 | foo | -| calls.rb:478:9:480:11 | bar | +| calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:374:1:378:3 | add_singleton | +| calls.rb:480:9:482:11 | foo | +| calls.rb:486:9:488:11 | bar | +| calls.rb:661:1:665:3 | capture_parameter | | private.rb:2:11:3:5 | private1 | | private.rb:8:3:9:5 | private2 | | private.rb:14:3:15:5 | private3 | @@ -459,42 +475,43 @@ publicMethod | calls.rb:311:5:314:7 | instance | | calls.rb:316:5:318:7 | singleton | | calls.rb:326:5:328:7 | instance | -| calls.rb:332:5:334:7 | instance | -| calls.rb:338:5:340:7 | instance | -| calls.rb:368:5:370:7 | instance | -| calls.rb:379:9:381:11 | singleton1 | -| calls.rb:383:9:385:11 | call_singleton1 | -| calls.rb:387:9:389:11 | factory | -| calls.rb:392:5:394:7 | singleton2 | -| calls.rb:396:5:398:7 | call_singleton2 | -| calls.rb:402:5:404:7 | instance1 | -| calls.rb:414:9:416:11 | singleton1 | -| calls.rb:419:5:421:7 | singleton2 | -| calls.rb:423:5:425:7 | instance1 | -| calls.rb:435:9:437:11 | m1 | -| calls.rb:440:5:452:7 | m2 | -| calls.rb:443:9:449:11 | m3 | -| calls.rb:446:13:448:15 | m4 | -| calls.rb:456:13:458:15 | m5 | -| calls.rb:497:5:499:7 | singleton | -| calls.rb:538:5:543:7 | baz | -| calls.rb:551:5:554:7 | baz | -| calls.rb:565:5:566:7 | singleton | -| calls.rb:571:5:574:7 | mid_method | -| calls.rb:577:5:578:7 | singleton2 | -| calls.rb:584:5:585:7 | singleton1 | -| calls.rb:587:5:589:7 | call_singleton1 | -| calls.rb:591:5:593:7 | call_call_singleton1 | -| calls.rb:597:5:598:7 | singleton1 | -| calls.rb:600:5:602:7 | call_singleton1 | -| calls.rb:606:5:607:7 | singleton1 | -| calls.rb:609:5:611:7 | call_singleton1 | -| calls.rb:619:5:621:7 | foo | -| calls.rb:622:5:623:7 | bar | -| calls.rb:628:5:630:7 | bar | -| calls.rb:634:5:636:7 | new | +| calls.rb:330:5:332:7 | return_self | +| calls.rb:336:5:338:7 | instance | +| calls.rb:342:5:344:7 | instance | +| calls.rb:375:5:377:7 | instance | +| calls.rb:387:9:389:11 | singleton1 | +| calls.rb:391:9:393:11 | call_singleton1 | +| calls.rb:395:9:397:11 | factory | +| calls.rb:400:5:402:7 | singleton2 | +| calls.rb:404:5:406:7 | call_singleton2 | +| calls.rb:410:5:412:7 | instance1 | +| calls.rb:422:9:424:11 | singleton1 | +| calls.rb:427:5:429:7 | singleton2 | +| calls.rb:431:5:433:7 | instance1 | +| calls.rb:443:9:445:11 | m1 | +| calls.rb:448:5:460:7 | m2 | +| calls.rb:451:9:457:11 | m3 | +| calls.rb:454:13:456:15 | m4 | +| calls.rb:464:13:466:15 | m5 | +| calls.rb:505:5:507:7 | singleton | +| calls.rb:546:5:551:7 | baz | +| calls.rb:559:5:562:7 | baz | +| calls.rb:573:5:574:7 | singleton | +| calls.rb:579:5:582:7 | mid_method | +| calls.rb:585:5:586:7 | singleton2 | +| calls.rb:592:5:593:7 | singleton1 | +| calls.rb:595:5:597:7 | call_singleton1 | +| calls.rb:599:5:601:7 | call_call_singleton1 | +| calls.rb:605:5:606:7 | singleton1 | +| calls.rb:608:5:610:7 | call_singleton1 | +| calls.rb:614:5:615:7 | singleton1 | +| calls.rb:617:5:619:7 | call_singleton1 | +| calls.rb:627:5:629:7 | foo | +| calls.rb:630:5:631:7 | bar | +| calls.rb:636:5:638:7 | bar | | calls.rb:642:5:644:7 | new | -| calls.rb:646:5:648:7 | instance | +| calls.rb:650:5:652:7 | new | +| calls.rb:654:5:656:7 | instance | | hello.rb:2:5:4:7 | hello | | hello.rb:5:5:7:7 | world | | hello.rb:13:5:15:7 | message | @@ -522,7 +539,7 @@ publicMethod | toplevel_self_singleton.rb:26:9:27:11 | call_me | | toplevel_self_singleton.rb:29:9:32:11 | call_you | protectedMethod -| calls.rb:526:15:528:7 | foo | -| calls.rb:534:15:536:7 | bar | +| calls.rb:534:15:536:7 | foo | +| calls.rb:542:15:544:7 | bar | | private.rb:32:3:33:5 | protected1 | | private.rb:35:3:36:5 | protected2 | diff --git a/ruby/ql/test/library-tests/modules/calls.rb b/ruby/ql/test/library-tests/modules/calls.rb index 27d90f84e93..ed0ee9528d6 100644 --- a/ruby/ql/test/library-tests/modules/calls.rb +++ b/ruby/ql/test/library-tests/modules/calls.rb @@ -326,6 +326,10 @@ class C1 def instance puts "C1#instance" end + + def return_self + self + end end class C2 < C1 @@ -360,10 +364,13 @@ end c1 = C1.new c1.instance + pattern_dispatch (C1.new) pattern_dispatch (C2.new) pattern_dispatch (C3.new) +C3.new.return_self.instance + def add_singleton x def x.instance puts "instance_on x" @@ -373,6 +380,7 @@ end c3 = C1.new add_singleton c3 c3.instance +c3.return_self.instance class SingletonOverride1 class << self @@ -649,3 +657,11 @@ class CustomNew2 end CustomNew2.new.instance + +def capture_parameter x + [0,1,2].each do + x + end +end + +(capture_parameter C1.new).instance # NoMethodError diff --git a/ruby/ql/test/library-tests/modules/methods.expected b/ruby/ql/test/library-tests/modules/methods.expected index cb936f30778..19d39d0ed6a 100644 --- a/ruby/ql/test/library-tests/modules/methods.expected +++ b/ruby/ql/test/library-tests/modules/methods.expected @@ -10,9 +10,10 @@ getMethod | calls.rb:105:1:113:3 | Module | module_eval | calls.rb:107:5:107:24 | module_eval | | calls.rb:105:1:113:3 | Module | prepend | calls.rb:111:5:111:20 | prepend | | calls.rb:105:1:113:3 | Module | private | calls.rb:112:5:112:20 | private | -| calls.rb:115:1:118:3 | Object | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:115:1:118:3 | Object | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:115:1:118:3 | Object | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:115:1:118:3 | Object | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:115:1:118:3 | Object | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:115:1:118:3 | Object | create | calls.rb:278:1:286:3 | create | | calls.rb:115:1:118:3 | Object | foo | calls.rb:1:1:3:3 | foo | | calls.rb:115:1:118:3 | Object | foo | calls.rb:85:1:89:3 | foo | @@ -20,7 +21,7 @@ getMethod | calls.rb:115:1:118:3 | Object | indirect | calls.rb:158:1:160:3 | indirect | | calls.rb:115:1:118:3 | Object | new | calls.rb:117:5:117:16 | new | | calls.rb:115:1:118:3 | Object | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:115:1:118:3 | Object | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:115:1:118:3 | Object | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:115:1:118:3 | Object | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:115:1:118:3 | Object | private_on_main | private.rb:51:1:52:3 | private_on_main | | calls.rb:120:1:123:3 | Hash | [] | calls.rb:122:5:122:31 | [] | @@ -33,22 +34,23 @@ getMethod | calls.rb:190:1:226:3 | Singletons | call_singleton_g | calls.rb:223:5:225:7 | call_singleton_g | | calls.rb:190:1:226:3 | Singletons | instance | calls.rb:210:5:215:7 | instance | | calls.rb:310:1:321:3 | SelfNew | instance | calls.rb:311:5:314:7 | instance | -| calls.rb:325:1:329:3 | C1 | instance | calls.rb:326:5:328:7 | instance | -| calls.rb:331:1:335:3 | C2 | instance | calls.rb:332:5:334:7 | instance | -| calls.rb:337:1:341:3 | C3 | instance | calls.rb:338:5:340:7 | instance | -| calls.rb:377:1:405:3 | SingletonOverride1 | instance1 | calls.rb:402:5:404:7 | instance1 | -| calls.rb:412:1:426:3 | SingletonOverride2 | instance1 | calls.rb:423:5:425:7 | instance1 | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | m1 | calls.rb:435:9:437:11 | m1 | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | m2 | calls.rb:440:5:452:7 | m2 | -| calls.rb:496:1:502:3 | ExtendSingletonMethod | singleton | calls.rb:497:5:499:7 | singleton | -| calls.rb:525:1:529:3 | ProtectedMethodInModule | foo | calls.rb:526:15:528:7 | foo | -| calls.rb:531:1:544:3 | ProtectedMethods | bar | calls.rb:534:15:536:7 | bar | -| calls.rb:531:1:544:3 | ProtectedMethods | baz | calls.rb:538:5:543:7 | baz | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | baz | calls.rb:551:5:554:7 | baz | -| calls.rb:618:1:624:3 | Included | bar | calls.rb:622:5:623:7 | bar | -| calls.rb:618:1:624:3 | Included | foo | calls.rb:619:5:621:7 | foo | -| calls.rb:626:1:631:3 | IncludesIncluded | bar | calls.rb:628:5:630:7 | bar | -| calls.rb:641:1:649:3 | CustomNew2 | instance | calls.rb:646:5:648:7 | instance | +| calls.rb:325:1:333:3 | C1 | instance | calls.rb:326:5:328:7 | instance | +| calls.rb:325:1:333:3 | C1 | return_self | calls.rb:330:5:332:7 | return_self | +| calls.rb:335:1:339:3 | C2 | instance | calls.rb:336:5:338:7 | instance | +| calls.rb:341:1:345:3 | C3 | instance | calls.rb:342:5:344:7 | instance | +| calls.rb:385:1:413:3 | SingletonOverride1 | instance1 | calls.rb:410:5:412:7 | instance1 | +| calls.rb:420:1:434:3 | SingletonOverride2 | instance1 | calls.rb:431:5:433:7 | instance1 | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | m1 | calls.rb:443:9:445:11 | m1 | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | m2 | calls.rb:448:5:460:7 | m2 | +| calls.rb:504:1:510:3 | ExtendSingletonMethod | singleton | calls.rb:505:5:507:7 | singleton | +| calls.rb:533:1:537:3 | ProtectedMethodInModule | foo | calls.rb:534:15:536:7 | foo | +| calls.rb:539:1:552:3 | ProtectedMethods | bar | calls.rb:542:15:544:7 | bar | +| calls.rb:539:1:552:3 | ProtectedMethods | baz | calls.rb:546:5:551:7 | baz | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | baz | calls.rb:559:5:562:7 | baz | +| calls.rb:626:1:632:3 | Included | bar | calls.rb:630:5:631:7 | bar | +| calls.rb:626:1:632:3 | Included | foo | calls.rb:627:5:629:7 | foo | +| calls.rb:634:1:639:3 | IncludesIncluded | bar | calls.rb:636:5:638:7 | bar | +| calls.rb:649:1:657:3 | CustomNew2 | instance | calls.rb:654:5:656:7 | instance | | hello.rb:1:1:8:3 | EnglishWords | hello | hello.rb:2:5:4:7 | hello | | hello.rb:1:1:8:3 | EnglishWords | world | hello.rb:5:5:7:7 | world | | hello.rb:11:1:16:3 | Greeting | message | hello.rb:13:5:15:7 | message | @@ -81,10 +83,11 @@ getMethod | private.rb:96:1:102:3 | PrivateOverride2 | m1 | private.rb:97:11:101:5 | m1 | lookupMethod | calls.rb:21:1:34:3 | M | instance_m | calls.rb:22:5:24:7 | instance_m | -| calls.rb:43:1:58:3 | C | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:43:1:58:3 | C | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:43:1:58:3 | C | baz | calls.rb:51:5:57:7 | baz | | calls.rb:43:1:58:3 | C | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:43:1:58:3 | C | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:43:1:58:3 | C | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:43:1:58:3 | C | create | calls.rb:278:1:286:3 | create | | calls.rb:43:1:58:3 | C | foo | calls.rb:1:1:3:3 | foo | | calls.rb:43:1:58:3 | C | foo | calls.rb:85:1:89:3 | foo | @@ -93,14 +96,15 @@ lookupMethod | calls.rb:43:1:58:3 | C | instance_m | calls.rb:22:5:24:7 | instance_m | | calls.rb:43:1:58:3 | C | new | calls.rb:117:5:117:16 | new | | calls.rb:43:1:58:3 | C | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:43:1:58:3 | C | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:43:1:58:3 | C | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:43:1:58:3 | C | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:43:1:58:3 | C | puts | calls.rb:102:5:102:30 | puts | | calls.rb:43:1:58:3 | C | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:65:1:69:3 | D | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:65:1:69:3 | D | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:65:1:69:3 | D | baz | calls.rb:66:5:68:7 | baz | | calls.rb:65:1:69:3 | D | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:65:1:69:3 | D | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:65:1:69:3 | D | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:65:1:69:3 | D | create | calls.rb:278:1:286:3 | create | | calls.rb:65:1:69:3 | D | foo | calls.rb:1:1:3:3 | foo | | calls.rb:65:1:69:3 | D | foo | calls.rb:85:1:89:3 | foo | @@ -109,7 +113,7 @@ lookupMethod | calls.rb:65:1:69:3 | D | instance_m | calls.rb:22:5:24:7 | instance_m | | calls.rb:65:1:69:3 | D | new | calls.rb:117:5:117:16 | new | | calls.rb:65:1:69:3 | D | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:65:1:69:3 | D | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:65:1:69:3 | D | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:65:1:69:3 | D | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:65:1:69:3 | D | puts | calls.rb:102:5:102:30 | puts | | calls.rb:65:1:69:3 | D | to_s | calls.rb:172:5:173:7 | to_s | @@ -118,10 +122,11 @@ lookupMethod | calls.rb:91:1:94:3 | Integer | new | calls.rb:117:5:117:16 | new | | calls.rb:91:1:94:3 | Integer | puts | calls.rb:102:5:102:30 | puts | | calls.rb:91:1:94:3 | Integer | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:96:1:98:3 | String | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:96:1:98:3 | String | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:96:1:98:3 | String | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:96:1:98:3 | String | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | | calls.rb:96:1:98:3 | String | capitalize | calls.rb:97:5:97:23 | capitalize | +| calls.rb:96:1:98:3 | String | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:96:1:98:3 | String | create | calls.rb:278:1:286:3 | create | | calls.rb:96:1:98:3 | String | foo | calls.rb:1:1:3:3 | foo | | calls.rb:96:1:98:3 | String | foo | calls.rb:85:1:89:3 | foo | @@ -129,14 +134,15 @@ lookupMethod | calls.rb:96:1:98:3 | String | indirect | calls.rb:158:1:160:3 | indirect | | calls.rb:96:1:98:3 | String | new | calls.rb:117:5:117:16 | new | | calls.rb:96:1:98:3 | String | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:96:1:98:3 | String | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:96:1:98:3 | String | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:96:1:98:3 | String | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:96:1:98:3 | String | puts | calls.rb:102:5:102:30 | puts | | calls.rb:96:1:98:3 | String | to_s | calls.rb:172:5:173:7 | to_s | | calls.rb:100:1:103:3 | Kernel | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:105:1:113:3 | Module | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:105:1:113:3 | Module | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:105:1:113:3 | Module | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:105:1:113:3 | Module | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:105:1:113:3 | Module | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:105:1:113:3 | Module | create | calls.rb:278:1:286:3 | create | | calls.rb:105:1:113:3 | Module | foo | calls.rb:1:1:3:3 | foo | | calls.rb:105:1:113:3 | Module | foo | calls.rb:85:1:89:3 | foo | @@ -146,15 +152,16 @@ lookupMethod | calls.rb:105:1:113:3 | Module | module_eval | calls.rb:107:5:107:24 | module_eval | | calls.rb:105:1:113:3 | Module | new | calls.rb:117:5:117:16 | new | | calls.rb:105:1:113:3 | Module | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:105:1:113:3 | Module | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:105:1:113:3 | Module | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:105:1:113:3 | Module | prepend | calls.rb:111:5:111:20 | prepend | | calls.rb:105:1:113:3 | Module | private | calls.rb:112:5:112:20 | private | | calls.rb:105:1:113:3 | Module | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:105:1:113:3 | Module | puts | calls.rb:102:5:102:30 | puts | | calls.rb:105:1:113:3 | Module | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:115:1:118:3 | Object | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:115:1:118:3 | Object | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:115:1:118:3 | Object | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:115:1:118:3 | Object | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:115:1:118:3 | Object | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:115:1:118:3 | Object | create | calls.rb:278:1:286:3 | create | | calls.rb:115:1:118:3 | Object | foo | calls.rb:1:1:3:3 | foo | | calls.rb:115:1:118:3 | Object | foo | calls.rb:85:1:89:3 | foo | @@ -162,15 +169,16 @@ lookupMethod | calls.rb:115:1:118:3 | Object | indirect | calls.rb:158:1:160:3 | indirect | | calls.rb:115:1:118:3 | Object | new | calls.rb:117:5:117:16 | new | | calls.rb:115:1:118:3 | Object | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:115:1:118:3 | Object | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:115:1:118:3 | Object | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:115:1:118:3 | Object | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:115:1:118:3 | Object | private_on_main | private.rb:51:1:52:3 | private_on_main | | calls.rb:115:1:118:3 | Object | puts | calls.rb:102:5:102:30 | puts | | calls.rb:115:1:118:3 | Object | to_s | calls.rb:172:5:173:7 | to_s | | calls.rb:120:1:123:3 | Hash | [] | calls.rb:122:5:122:31 | [] | -| calls.rb:120:1:123:3 | Hash | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:120:1:123:3 | Hash | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:120:1:123:3 | Hash | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:120:1:123:3 | Hash | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:120:1:123:3 | Hash | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:120:1:123:3 | Hash | create | calls.rb:278:1:286:3 | create | | calls.rb:120:1:123:3 | Hash | foo | calls.rb:1:1:3:3 | foo | | calls.rb:120:1:123:3 | Hash | foo | calls.rb:85:1:89:3 | foo | @@ -178,14 +186,15 @@ lookupMethod | calls.rb:120:1:123:3 | Hash | indirect | calls.rb:158:1:160:3 | indirect | | calls.rb:120:1:123:3 | Hash | new | calls.rb:117:5:117:16 | new | | calls.rb:120:1:123:3 | Hash | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:120:1:123:3 | Hash | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:120:1:123:3 | Hash | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:120:1:123:3 | Hash | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:120:1:123:3 | Hash | puts | calls.rb:102:5:102:30 | puts | | calls.rb:120:1:123:3 | Hash | to_s | calls.rb:172:5:173:7 | to_s | | calls.rb:125:1:138:3 | Array | [] | calls.rb:127:3:127:29 | [] | -| calls.rb:125:1:138:3 | Array | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:125:1:138:3 | Array | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:125:1:138:3 | Array | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:125:1:138:3 | Array | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:125:1:138:3 | Array | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:125:1:138:3 | Array | create | calls.rb:278:1:286:3 | create | | calls.rb:125:1:138:3 | Array | foo | calls.rb:1:1:3:3 | foo | | calls.rb:125:1:138:3 | Array | foo | calls.rb:85:1:89:3 | foo | @@ -195,13 +204,14 @@ lookupMethod | calls.rb:125:1:138:3 | Array | length | calls.rb:129:3:129:17 | length | | calls.rb:125:1:138:3 | Array | new | calls.rb:117:5:117:16 | new | | calls.rb:125:1:138:3 | Array | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:125:1:138:3 | Array | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:125:1:138:3 | Array | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:125:1:138:3 | Array | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:125:1:138:3 | Array | puts | calls.rb:102:5:102:30 | puts | | calls.rb:125:1:138:3 | Array | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:165:1:169:3 | S | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:165:1:169:3 | S | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:165:1:169:3 | S | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:165:1:169:3 | S | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:165:1:169:3 | S | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:165:1:169:3 | S | create | calls.rb:278:1:286:3 | create | | calls.rb:165:1:169:3 | S | foo | calls.rb:1:1:3:3 | foo | | calls.rb:165:1:169:3 | S | foo | calls.rb:85:1:89:3 | foo | @@ -209,14 +219,15 @@ lookupMethod | calls.rb:165:1:169:3 | S | indirect | calls.rb:158:1:160:3 | indirect | | calls.rb:165:1:169:3 | S | new | calls.rb:117:5:117:16 | new | | calls.rb:165:1:169:3 | S | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:165:1:169:3 | S | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:165:1:169:3 | S | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:165:1:169:3 | S | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:165:1:169:3 | S | puts | calls.rb:102:5:102:30 | puts | | calls.rb:165:1:169:3 | S | s_method | calls.rb:166:5:168:7 | s_method | | calls.rb:165:1:169:3 | S | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:171:1:174:3 | A | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:171:1:174:3 | A | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:171:1:174:3 | A | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:171:1:174:3 | A | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:171:1:174:3 | A | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:171:1:174:3 | A | create | calls.rb:278:1:286:3 | create | | calls.rb:171:1:174:3 | A | foo | calls.rb:1:1:3:3 | foo | | calls.rb:171:1:174:3 | A | foo | calls.rb:85:1:89:3 | foo | @@ -224,14 +235,15 @@ lookupMethod | calls.rb:171:1:174:3 | A | indirect | calls.rb:158:1:160:3 | indirect | | calls.rb:171:1:174:3 | A | new | calls.rb:117:5:117:16 | new | | calls.rb:171:1:174:3 | A | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:171:1:174:3 | A | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:171:1:174:3 | A | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:171:1:174:3 | A | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:171:1:174:3 | A | puts | calls.rb:102:5:102:30 | puts | | calls.rb:171:1:174:3 | A | s_method | calls.rb:166:5:168:7 | s_method | | calls.rb:171:1:174:3 | A | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:176:1:179:3 | B | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:176:1:179:3 | B | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:176:1:179:3 | B | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:176:1:179:3 | B | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:176:1:179:3 | B | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:176:1:179:3 | B | create | calls.rb:278:1:286:3 | create | | calls.rb:176:1:179:3 | B | foo | calls.rb:1:1:3:3 | foo | | calls.rb:176:1:179:3 | B | foo | calls.rb:85:1:89:3 | foo | @@ -239,15 +251,16 @@ lookupMethod | calls.rb:176:1:179:3 | B | indirect | calls.rb:158:1:160:3 | indirect | | calls.rb:176:1:179:3 | B | new | calls.rb:117:5:117:16 | new | | calls.rb:176:1:179:3 | B | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:176:1:179:3 | B | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:176:1:179:3 | B | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:176:1:179:3 | B | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:176:1:179:3 | B | puts | calls.rb:102:5:102:30 | puts | | calls.rb:176:1:179:3 | B | s_method | calls.rb:166:5:168:7 | s_method | | calls.rb:176:1:179:3 | B | to_s | calls.rb:177:5:178:7 | to_s | -| calls.rb:190:1:226:3 | Singletons | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:190:1:226:3 | Singletons | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:190:1:226:3 | Singletons | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:190:1:226:3 | Singletons | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | | calls.rb:190:1:226:3 | Singletons | call_singleton_g | calls.rb:223:5:225:7 | call_singleton_g | +| calls.rb:190:1:226:3 | Singletons | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:190:1:226:3 | Singletons | create | calls.rb:278:1:286:3 | create | | calls.rb:190:1:226:3 | Singletons | foo | calls.rb:1:1:3:3 | foo | | calls.rb:190:1:226:3 | Singletons | foo | calls.rb:85:1:89:3 | foo | @@ -256,13 +269,14 @@ lookupMethod | calls.rb:190:1:226:3 | Singletons | instance | calls.rb:210:5:215:7 | instance | | calls.rb:190:1:226:3 | Singletons | new | calls.rb:117:5:117:16 | new | | calls.rb:190:1:226:3 | Singletons | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:190:1:226:3 | Singletons | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:190:1:226:3 | Singletons | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:190:1:226:3 | Singletons | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:190:1:226:3 | Singletons | puts | calls.rb:102:5:102:30 | puts | | calls.rb:190:1:226:3 | Singletons | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:310:1:321:3 | SelfNew | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:310:1:321:3 | SelfNew | add_singleton | calls.rb:374:1:378:3 | add_singleton | | calls.rb:310:1:321:3 | SelfNew | call_block | calls.rb:81:1:83:3 | call_block | | calls.rb:310:1:321:3 | SelfNew | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:310:1:321:3 | SelfNew | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | | calls.rb:310:1:321:3 | SelfNew | create | calls.rb:278:1:286:3 | create | | calls.rb:310:1:321:3 | SelfNew | foo | calls.rb:1:1:3:3 | foo | | calls.rb:310:1:321:3 | SelfNew | foo | calls.rb:85:1:89:3 | foo | @@ -271,262 +285,282 @@ lookupMethod | calls.rb:310:1:321:3 | SelfNew | instance | calls.rb:311:5:314:7 | instance | | calls.rb:310:1:321:3 | SelfNew | new | calls.rb:117:5:117:16 | new | | calls.rb:310:1:321:3 | SelfNew | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:310:1:321:3 | SelfNew | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:310:1:321:3 | SelfNew | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | | calls.rb:310:1:321:3 | SelfNew | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:310:1:321:3 | SelfNew | puts | calls.rb:102:5:102:30 | puts | | calls.rb:310:1:321:3 | SelfNew | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:325:1:329:3 | C1 | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:325:1:329:3 | C1 | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:325:1:329:3 | C1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:325:1:329:3 | C1 | create | calls.rb:278:1:286:3 | create | -| calls.rb:325:1:329:3 | C1 | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:325:1:329:3 | C1 | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:325:1:329:3 | C1 | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:325:1:329:3 | C1 | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:325:1:329:3 | C1 | instance | calls.rb:326:5:328:7 | instance | -| calls.rb:325:1:329:3 | C1 | new | calls.rb:117:5:117:16 | new | -| calls.rb:325:1:329:3 | C1 | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:325:1:329:3 | C1 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:325:1:329:3 | C1 | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:325:1:329:3 | C1 | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:325:1:329:3 | C1 | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:331:1:335:3 | C2 | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:331:1:335:3 | C2 | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:331:1:335:3 | C2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:331:1:335:3 | C2 | create | calls.rb:278:1:286:3 | create | -| calls.rb:331:1:335:3 | C2 | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:331:1:335:3 | C2 | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:331:1:335:3 | C2 | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:331:1:335:3 | C2 | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:331:1:335:3 | C2 | instance | calls.rb:332:5:334:7 | instance | -| calls.rb:331:1:335:3 | C2 | new | calls.rb:117:5:117:16 | new | -| calls.rb:331:1:335:3 | C2 | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:331:1:335:3 | C2 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:331:1:335:3 | C2 | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:331:1:335:3 | C2 | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:331:1:335:3 | C2 | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:337:1:341:3 | C3 | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:337:1:341:3 | C3 | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:337:1:341:3 | C3 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:337:1:341:3 | C3 | create | calls.rb:278:1:286:3 | create | -| calls.rb:337:1:341:3 | C3 | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:337:1:341:3 | C3 | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:337:1:341:3 | C3 | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:337:1:341:3 | C3 | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:337:1:341:3 | C3 | instance | calls.rb:338:5:340:7 | instance | -| calls.rb:337:1:341:3 | C3 | new | calls.rb:117:5:117:16 | new | -| calls.rb:337:1:341:3 | C3 | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:337:1:341:3 | C3 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:337:1:341:3 | C3 | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:337:1:341:3 | C3 | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:337:1:341:3 | C3 | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:377:1:405:3 | SingletonOverride1 | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:377:1:405:3 | SingletonOverride1 | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:377:1:405:3 | SingletonOverride1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:377:1:405:3 | SingletonOverride1 | create | calls.rb:278:1:286:3 | create | -| calls.rb:377:1:405:3 | SingletonOverride1 | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:377:1:405:3 | SingletonOverride1 | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:377:1:405:3 | SingletonOverride1 | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:377:1:405:3 | SingletonOverride1 | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:377:1:405:3 | SingletonOverride1 | instance1 | calls.rb:402:5:404:7 | instance1 | -| calls.rb:377:1:405:3 | SingletonOverride1 | new | calls.rb:117:5:117:16 | new | -| calls.rb:377:1:405:3 | SingletonOverride1 | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:377:1:405:3 | SingletonOverride1 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:377:1:405:3 | SingletonOverride1 | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:377:1:405:3 | SingletonOverride1 | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:377:1:405:3 | SingletonOverride1 | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:412:1:426:3 | SingletonOverride2 | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:412:1:426:3 | SingletonOverride2 | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:412:1:426:3 | SingletonOverride2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:412:1:426:3 | SingletonOverride2 | create | calls.rb:278:1:286:3 | create | -| calls.rb:412:1:426:3 | SingletonOverride2 | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:412:1:426:3 | SingletonOverride2 | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:412:1:426:3 | SingletonOverride2 | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:412:1:426:3 | SingletonOverride2 | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:412:1:426:3 | SingletonOverride2 | instance1 | calls.rb:423:5:425:7 | instance1 | -| calls.rb:412:1:426:3 | SingletonOverride2 | new | calls.rb:117:5:117:16 | new | -| calls.rb:412:1:426:3 | SingletonOverride2 | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:412:1:426:3 | SingletonOverride2 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:412:1:426:3 | SingletonOverride2 | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:412:1:426:3 | SingletonOverride2 | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:412:1:426:3 | SingletonOverride2 | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | create | calls.rb:278:1:286:3 | create | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | m1 | calls.rb:435:9:437:11 | m1 | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | m2 | calls.rb:440:5:452:7 | m2 | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | new | calls.rb:117:5:117:16 | new | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:496:1:502:3 | ExtendSingletonMethod | singleton | calls.rb:497:5:499:7 | singleton | -| calls.rb:525:1:529:3 | ProtectedMethodInModule | foo | calls.rb:526:15:528:7 | foo | -| calls.rb:531:1:544:3 | ProtectedMethods | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:531:1:544:3 | ProtectedMethods | bar | calls.rb:534:15:536:7 | bar | -| calls.rb:531:1:544:3 | ProtectedMethods | baz | calls.rb:538:5:543:7 | baz | -| calls.rb:531:1:544:3 | ProtectedMethods | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:531:1:544:3 | ProtectedMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:531:1:544:3 | ProtectedMethods | create | calls.rb:278:1:286:3 | create | -| calls.rb:531:1:544:3 | ProtectedMethods | foo | calls.rb:526:15:528:7 | foo | -| calls.rb:531:1:544:3 | ProtectedMethods | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:531:1:544:3 | ProtectedMethods | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:531:1:544:3 | ProtectedMethods | new | calls.rb:117:5:117:16 | new | -| calls.rb:531:1:544:3 | ProtectedMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:531:1:544:3 | ProtectedMethods | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:531:1:544:3 | ProtectedMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:531:1:544:3 | ProtectedMethods | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:531:1:544:3 | ProtectedMethods | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | bar | calls.rb:534:15:536:7 | bar | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | baz | calls.rb:551:5:554:7 | baz | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | create | calls.rb:278:1:286:3 | create | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | foo | calls.rb:526:15:528:7 | foo | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | new | calls.rb:117:5:117:16 | new | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | create | calls.rb:278:1:286:3 | create | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | new | calls.rb:117:5:117:16 | new | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | create | calls.rb:278:1:286:3 | create | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | new | calls.rb:117:5:117:16 | new | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | create | calls.rb:278:1:286:3 | create | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | new | calls.rb:117:5:117:16 | new | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:583:1:594:3 | SingletonA | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:583:1:594:3 | SingletonA | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:583:1:594:3 | SingletonA | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:583:1:594:3 | SingletonA | create | calls.rb:278:1:286:3 | create | -| calls.rb:583:1:594:3 | SingletonA | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:583:1:594:3 | SingletonA | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:583:1:594:3 | SingletonA | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:583:1:594:3 | SingletonA | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:583:1:594:3 | SingletonA | new | calls.rb:117:5:117:16 | new | -| calls.rb:583:1:594:3 | SingletonA | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:583:1:594:3 | SingletonA | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:583:1:594:3 | SingletonA | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:583:1:594:3 | SingletonA | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:583:1:594:3 | SingletonA | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:596:1:603:3 | SingletonB | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:596:1:603:3 | SingletonB | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:596:1:603:3 | SingletonB | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:596:1:603:3 | SingletonB | create | calls.rb:278:1:286:3 | create | -| calls.rb:596:1:603:3 | SingletonB | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:596:1:603:3 | SingletonB | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:596:1:603:3 | SingletonB | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:596:1:603:3 | SingletonB | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:596:1:603:3 | SingletonB | new | calls.rb:117:5:117:16 | new | -| calls.rb:596:1:603:3 | SingletonB | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:596:1:603:3 | SingletonB | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:596:1:603:3 | SingletonB | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:596:1:603:3 | SingletonB | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:596:1:603:3 | SingletonB | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:605:1:612:3 | SingletonC | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:605:1:612:3 | SingletonC | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:605:1:612:3 | SingletonC | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:605:1:612:3 | SingletonC | create | calls.rb:278:1:286:3 | create | -| calls.rb:605:1:612:3 | SingletonC | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:605:1:612:3 | SingletonC | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:605:1:612:3 | SingletonC | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:605:1:612:3 | SingletonC | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:605:1:612:3 | SingletonC | new | calls.rb:117:5:117:16 | new | -| calls.rb:605:1:612:3 | SingletonC | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:605:1:612:3 | SingletonC | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:605:1:612:3 | SingletonC | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:605:1:612:3 | SingletonC | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:605:1:612:3 | SingletonC | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:618:1:624:3 | Included | bar | calls.rb:622:5:623:7 | bar | -| calls.rb:618:1:624:3 | Included | foo | calls.rb:619:5:621:7 | foo | -| calls.rb:626:1:631:3 | IncludesIncluded | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:626:1:631:3 | IncludesIncluded | bar | calls.rb:628:5:630:7 | bar | -| calls.rb:626:1:631:3 | IncludesIncluded | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:626:1:631:3 | IncludesIncluded | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:626:1:631:3 | IncludesIncluded | create | calls.rb:278:1:286:3 | create | -| calls.rb:626:1:631:3 | IncludesIncluded | foo | calls.rb:619:5:621:7 | foo | -| calls.rb:626:1:631:3 | IncludesIncluded | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:626:1:631:3 | IncludesIncluded | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:626:1:631:3 | IncludesIncluded | new | calls.rb:117:5:117:16 | new | -| calls.rb:626:1:631:3 | IncludesIncluded | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:626:1:631:3 | IncludesIncluded | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:626:1:631:3 | IncludesIncluded | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:626:1:631:3 | IncludesIncluded | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:626:1:631:3 | IncludesIncluded | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:633:1:637:3 | CustomNew1 | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:633:1:637:3 | CustomNew1 | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:633:1:637:3 | CustomNew1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:633:1:637:3 | CustomNew1 | create | calls.rb:278:1:286:3 | create | -| calls.rb:633:1:637:3 | CustomNew1 | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:633:1:637:3 | CustomNew1 | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:633:1:637:3 | CustomNew1 | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:633:1:637:3 | CustomNew1 | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:633:1:637:3 | CustomNew1 | new | calls.rb:117:5:117:16 | new | -| calls.rb:633:1:637:3 | CustomNew1 | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:633:1:637:3 | CustomNew1 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:633:1:637:3 | CustomNew1 | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:633:1:637:3 | CustomNew1 | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:633:1:637:3 | CustomNew1 | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:641:1:649:3 | CustomNew2 | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:641:1:649:3 | CustomNew2 | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:641:1:649:3 | CustomNew2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:641:1:649:3 | CustomNew2 | create | calls.rb:278:1:286:3 | create | -| calls.rb:641:1:649:3 | CustomNew2 | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:641:1:649:3 | CustomNew2 | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:641:1:649:3 | CustomNew2 | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:641:1:649:3 | CustomNew2 | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:641:1:649:3 | CustomNew2 | instance | calls.rb:646:5:648:7 | instance | -| calls.rb:641:1:649:3 | CustomNew2 | new | calls.rb:117:5:117:16 | new | -| calls.rb:641:1:649:3 | CustomNew2 | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:641:1:649:3 | CustomNew2 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:641:1:649:3 | CustomNew2 | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:641:1:649:3 | CustomNew2 | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:641:1:649:3 | CustomNew2 | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:325:1:333:3 | C1 | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:325:1:333:3 | C1 | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:325:1:333:3 | C1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:325:1:333:3 | C1 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:325:1:333:3 | C1 | create | calls.rb:278:1:286:3 | create | +| calls.rb:325:1:333:3 | C1 | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:325:1:333:3 | C1 | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:325:1:333:3 | C1 | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:325:1:333:3 | C1 | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:325:1:333:3 | C1 | instance | calls.rb:326:5:328:7 | instance | +| calls.rb:325:1:333:3 | C1 | new | calls.rb:117:5:117:16 | new | +| calls.rb:325:1:333:3 | C1 | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:325:1:333:3 | C1 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:325:1:333:3 | C1 | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:325:1:333:3 | C1 | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:325:1:333:3 | C1 | return_self | calls.rb:330:5:332:7 | return_self | +| calls.rb:325:1:333:3 | C1 | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:335:1:339:3 | C2 | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:335:1:339:3 | C2 | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:335:1:339:3 | C2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:335:1:339:3 | C2 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:335:1:339:3 | C2 | create | calls.rb:278:1:286:3 | create | +| calls.rb:335:1:339:3 | C2 | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:335:1:339:3 | C2 | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:335:1:339:3 | C2 | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:335:1:339:3 | C2 | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:335:1:339:3 | C2 | instance | calls.rb:336:5:338:7 | instance | +| calls.rb:335:1:339:3 | C2 | new | calls.rb:117:5:117:16 | new | +| calls.rb:335:1:339:3 | C2 | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:335:1:339:3 | C2 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:335:1:339:3 | C2 | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:335:1:339:3 | C2 | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:335:1:339:3 | C2 | return_self | calls.rb:330:5:332:7 | return_self | +| calls.rb:335:1:339:3 | C2 | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:341:1:345:3 | C3 | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:341:1:345:3 | C3 | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:341:1:345:3 | C3 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:341:1:345:3 | C3 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:341:1:345:3 | C3 | create | calls.rb:278:1:286:3 | create | +| calls.rb:341:1:345:3 | C3 | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:341:1:345:3 | C3 | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:341:1:345:3 | C3 | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:341:1:345:3 | C3 | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:341:1:345:3 | C3 | instance | calls.rb:342:5:344:7 | instance | +| calls.rb:341:1:345:3 | C3 | new | calls.rb:117:5:117:16 | new | +| calls.rb:341:1:345:3 | C3 | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:341:1:345:3 | C3 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:341:1:345:3 | C3 | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:341:1:345:3 | C3 | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:341:1:345:3 | C3 | return_self | calls.rb:330:5:332:7 | return_self | +| calls.rb:341:1:345:3 | C3 | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:385:1:413:3 | SingletonOverride1 | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:385:1:413:3 | SingletonOverride1 | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:385:1:413:3 | SingletonOverride1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:385:1:413:3 | SingletonOverride1 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:385:1:413:3 | SingletonOverride1 | create | calls.rb:278:1:286:3 | create | +| calls.rb:385:1:413:3 | SingletonOverride1 | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:385:1:413:3 | SingletonOverride1 | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:385:1:413:3 | SingletonOverride1 | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:385:1:413:3 | SingletonOverride1 | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:385:1:413:3 | SingletonOverride1 | instance1 | calls.rb:410:5:412:7 | instance1 | +| calls.rb:385:1:413:3 | SingletonOverride1 | new | calls.rb:117:5:117:16 | new | +| calls.rb:385:1:413:3 | SingletonOverride1 | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:385:1:413:3 | SingletonOverride1 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:385:1:413:3 | SingletonOverride1 | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:385:1:413:3 | SingletonOverride1 | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:385:1:413:3 | SingletonOverride1 | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:420:1:434:3 | SingletonOverride2 | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:420:1:434:3 | SingletonOverride2 | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:420:1:434:3 | SingletonOverride2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:420:1:434:3 | SingletonOverride2 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:420:1:434:3 | SingletonOverride2 | create | calls.rb:278:1:286:3 | create | +| calls.rb:420:1:434:3 | SingletonOverride2 | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:420:1:434:3 | SingletonOverride2 | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:420:1:434:3 | SingletonOverride2 | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:420:1:434:3 | SingletonOverride2 | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:420:1:434:3 | SingletonOverride2 | instance1 | calls.rb:431:5:433:7 | instance1 | +| calls.rb:420:1:434:3 | SingletonOverride2 | new | calls.rb:117:5:117:16 | new | +| calls.rb:420:1:434:3 | SingletonOverride2 | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:420:1:434:3 | SingletonOverride2 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:420:1:434:3 | SingletonOverride2 | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:420:1:434:3 | SingletonOverride2 | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:420:1:434:3 | SingletonOverride2 | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | create | calls.rb:278:1:286:3 | create | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | m1 | calls.rb:443:9:445:11 | m1 | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | m2 | calls.rb:448:5:460:7 | m2 | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | new | calls.rb:117:5:117:16 | new | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:504:1:510:3 | ExtendSingletonMethod | singleton | calls.rb:505:5:507:7 | singleton | +| calls.rb:533:1:537:3 | ProtectedMethodInModule | foo | calls.rb:534:15:536:7 | foo | +| calls.rb:539:1:552:3 | ProtectedMethods | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:539:1:552:3 | ProtectedMethods | bar | calls.rb:542:15:544:7 | bar | +| calls.rb:539:1:552:3 | ProtectedMethods | baz | calls.rb:546:5:551:7 | baz | +| calls.rb:539:1:552:3 | ProtectedMethods | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:539:1:552:3 | ProtectedMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:539:1:552:3 | ProtectedMethods | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:539:1:552:3 | ProtectedMethods | create | calls.rb:278:1:286:3 | create | +| calls.rb:539:1:552:3 | ProtectedMethods | foo | calls.rb:534:15:536:7 | foo | +| calls.rb:539:1:552:3 | ProtectedMethods | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:539:1:552:3 | ProtectedMethods | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:539:1:552:3 | ProtectedMethods | new | calls.rb:117:5:117:16 | new | +| calls.rb:539:1:552:3 | ProtectedMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:539:1:552:3 | ProtectedMethods | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:539:1:552:3 | ProtectedMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:539:1:552:3 | ProtectedMethods | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:539:1:552:3 | ProtectedMethods | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | bar | calls.rb:542:15:544:7 | bar | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | baz | calls.rb:559:5:562:7 | baz | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | create | calls.rb:278:1:286:3 | create | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | foo | calls.rb:534:15:536:7 | foo | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | new | calls.rb:117:5:117:16 | new | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | create | calls.rb:278:1:286:3 | create | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | new | calls.rb:117:5:117:16 | new | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | create | calls.rb:278:1:286:3 | create | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | new | calls.rb:117:5:117:16 | new | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | create | calls.rb:278:1:286:3 | create | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | new | calls.rb:117:5:117:16 | new | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:591:1:602:3 | SingletonA | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:591:1:602:3 | SingletonA | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:591:1:602:3 | SingletonA | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:591:1:602:3 | SingletonA | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:591:1:602:3 | SingletonA | create | calls.rb:278:1:286:3 | create | +| calls.rb:591:1:602:3 | SingletonA | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:591:1:602:3 | SingletonA | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:591:1:602:3 | SingletonA | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:591:1:602:3 | SingletonA | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:591:1:602:3 | SingletonA | new | calls.rb:117:5:117:16 | new | +| calls.rb:591:1:602:3 | SingletonA | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:591:1:602:3 | SingletonA | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:591:1:602:3 | SingletonA | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:591:1:602:3 | SingletonA | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:591:1:602:3 | SingletonA | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:604:1:611:3 | SingletonB | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:604:1:611:3 | SingletonB | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:604:1:611:3 | SingletonB | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:604:1:611:3 | SingletonB | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:604:1:611:3 | SingletonB | create | calls.rb:278:1:286:3 | create | +| calls.rb:604:1:611:3 | SingletonB | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:604:1:611:3 | SingletonB | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:604:1:611:3 | SingletonB | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:604:1:611:3 | SingletonB | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:604:1:611:3 | SingletonB | new | calls.rb:117:5:117:16 | new | +| calls.rb:604:1:611:3 | SingletonB | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:604:1:611:3 | SingletonB | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:604:1:611:3 | SingletonB | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:604:1:611:3 | SingletonB | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:604:1:611:3 | SingletonB | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:613:1:620:3 | SingletonC | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:613:1:620:3 | SingletonC | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:613:1:620:3 | SingletonC | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:613:1:620:3 | SingletonC | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:613:1:620:3 | SingletonC | create | calls.rb:278:1:286:3 | create | +| calls.rb:613:1:620:3 | SingletonC | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:613:1:620:3 | SingletonC | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:613:1:620:3 | SingletonC | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:613:1:620:3 | SingletonC | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:613:1:620:3 | SingletonC | new | calls.rb:117:5:117:16 | new | +| calls.rb:613:1:620:3 | SingletonC | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:613:1:620:3 | SingletonC | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:613:1:620:3 | SingletonC | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:613:1:620:3 | SingletonC | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:613:1:620:3 | SingletonC | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:626:1:632:3 | Included | bar | calls.rb:630:5:631:7 | bar | +| calls.rb:626:1:632:3 | Included | foo | calls.rb:627:5:629:7 | foo | +| calls.rb:634:1:639:3 | IncludesIncluded | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:634:1:639:3 | IncludesIncluded | bar | calls.rb:636:5:638:7 | bar | +| calls.rb:634:1:639:3 | IncludesIncluded | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:634:1:639:3 | IncludesIncluded | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:634:1:639:3 | IncludesIncluded | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:634:1:639:3 | IncludesIncluded | create | calls.rb:278:1:286:3 | create | +| calls.rb:634:1:639:3 | IncludesIncluded | foo | calls.rb:627:5:629:7 | foo | +| calls.rb:634:1:639:3 | IncludesIncluded | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:634:1:639:3 | IncludesIncluded | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:634:1:639:3 | IncludesIncluded | new | calls.rb:117:5:117:16 | new | +| calls.rb:634:1:639:3 | IncludesIncluded | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:634:1:639:3 | IncludesIncluded | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:634:1:639:3 | IncludesIncluded | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:634:1:639:3 | IncludesIncluded | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:634:1:639:3 | IncludesIncluded | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:641:1:645:3 | CustomNew1 | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:641:1:645:3 | CustomNew1 | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:641:1:645:3 | CustomNew1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:641:1:645:3 | CustomNew1 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:641:1:645:3 | CustomNew1 | create | calls.rb:278:1:286:3 | create | +| calls.rb:641:1:645:3 | CustomNew1 | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:641:1:645:3 | CustomNew1 | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:641:1:645:3 | CustomNew1 | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:641:1:645:3 | CustomNew1 | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:641:1:645:3 | CustomNew1 | new | calls.rb:117:5:117:16 | new | +| calls.rb:641:1:645:3 | CustomNew1 | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:641:1:645:3 | CustomNew1 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:641:1:645:3 | CustomNew1 | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:641:1:645:3 | CustomNew1 | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:641:1:645:3 | CustomNew1 | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:649:1:657:3 | CustomNew2 | add_singleton | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:649:1:657:3 | CustomNew2 | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:649:1:657:3 | CustomNew2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:649:1:657:3 | CustomNew2 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:649:1:657:3 | CustomNew2 | create | calls.rb:278:1:286:3 | create | +| calls.rb:649:1:657:3 | CustomNew2 | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:649:1:657:3 | CustomNew2 | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:649:1:657:3 | CustomNew2 | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:649:1:657:3 | CustomNew2 | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:649:1:657:3 | CustomNew2 | instance | calls.rb:654:5:656:7 | instance | +| calls.rb:649:1:657:3 | CustomNew2 | new | calls.rb:117:5:117:16 | new | +| calls.rb:649:1:657:3 | CustomNew2 | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:649:1:657:3 | CustomNew2 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:649:1:657:3 | CustomNew2 | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:649:1:657:3 | CustomNew2 | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:649:1:657:3 | CustomNew2 | to_s | calls.rb:172:5:173:7 | to_s | | file://:0:0:0:0 | Class | include | calls.rb:108:5:110:7 | include | | file://:0:0:0:0 | Class | module_eval | calls.rb:107:5:107:24 | module_eval | | file://:0:0:0:0 | Class | new | calls.rb:117:5:117:16 | new | @@ -864,176 +898,188 @@ enclosingMethod | calls.rb:327:9:327:26 | self | calls.rb:326:5:328:7 | instance | | calls.rb:327:14:327:26 | "C1#instance" | calls.rb:326:5:328:7 | instance | | calls.rb:327:15:327:25 | C1#instance | calls.rb:326:5:328:7 | instance | -| calls.rb:333:9:333:26 | call to puts | calls.rb:332:5:334:7 | instance | -| calls.rb:333:9:333:26 | self | calls.rb:332:5:334:7 | instance | -| calls.rb:333:14:333:26 | "C2#instance" | calls.rb:332:5:334:7 | instance | -| calls.rb:333:15:333:25 | C2#instance | calls.rb:332:5:334:7 | instance | -| calls.rb:339:9:339:26 | call to puts | calls.rb:338:5:340:7 | instance | -| calls.rb:339:9:339:26 | self | calls.rb:338:5:340:7 | instance | -| calls.rb:339:14:339:26 | "C3#instance" | calls.rb:338:5:340:7 | instance | -| calls.rb:339:15:339:25 | C3#instance | calls.rb:338:5:340:7 | instance | -| calls.rb:343:22:343:22 | x | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:343:22:343:22 | x | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:344:5:352:7 | case ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:344:10:344:10 | x | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:345:5:346:18 | when ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:345:10:345:11 | C3 | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:345:12:346:18 | then ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:346:9:346:9 | x | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:346:9:346:18 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:347:5:348:18 | when ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:347:10:347:11 | C2 | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:347:12:348:18 | then ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:348:9:348:9 | x | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:348:9:348:18 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:349:5:350:18 | when ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:349:10:349:11 | C1 | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:349:12:350:18 | then ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:350:9:350:9 | x | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:350:9:350:18 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:351:5:351:8 | else ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:354:5:358:7 | case ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:354:10:354:10 | x | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:355:9:355:29 | in ... then ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:355:12:355:13 | C3 | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:355:15:355:29 | then ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:355:20:355:20 | x | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:355:20:355:29 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:356:9:356:36 | in ... then ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:356:12:356:13 | C2 | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:356:12:356:19 | ... => ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:356:18:356:19 | c2 | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:356:21:356:36 | then ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:356:26:356:27 | c2 | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:356:26:356:36 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:357:9:357:36 | in ... then ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:357:12:357:13 | C1 | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:357:12:357:19 | ... => ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:357:18:357:19 | c1 | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:357:21:357:36 | then ... | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:357:26:357:27 | c1 | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:357:26:357:36 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:367:19:367:19 | x | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:367:19:367:19 | x | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:368:5:370:7 | instance | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:368:9:368:9 | x | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:369:9:369:28 | call to puts | calls.rb:368:5:370:7 | instance | -| calls.rb:369:9:369:28 | self | calls.rb:368:5:370:7 | instance | -| calls.rb:369:14:369:28 | "instance_on x" | calls.rb:368:5:370:7 | instance | -| calls.rb:369:15:369:27 | instance_on x | calls.rb:368:5:370:7 | instance | -| calls.rb:380:13:380:48 | call to puts | calls.rb:379:9:381:11 | singleton1 | -| calls.rb:380:13:380:48 | self | calls.rb:379:9:381:11 | singleton1 | -| calls.rb:380:18:380:48 | "SingletonOverride1#singleton1" | calls.rb:379:9:381:11 | singleton1 | -| calls.rb:380:19:380:47 | SingletonOverride1#singleton1 | calls.rb:379:9:381:11 | singleton1 | -| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:383:9:385:11 | call_singleton1 | -| calls.rb:384:13:384:22 | self | calls.rb:383:9:385:11 | call_singleton1 | -| calls.rb:388:13:388:16 | self | calls.rb:387:9:389:11 | factory | -| calls.rb:388:13:388:20 | call to new | calls.rb:387:9:389:11 | factory | -| calls.rb:388:13:388:30 | call to instance1 | calls.rb:387:9:389:11 | factory | -| calls.rb:393:9:393:44 | call to puts | calls.rb:392:5:394:7 | singleton2 | -| calls.rb:393:9:393:44 | self | calls.rb:392:5:394:7 | singleton2 | -| calls.rb:393:14:393:44 | "SingletonOverride1#singleton2" | calls.rb:392:5:394:7 | singleton2 | -| calls.rb:393:15:393:43 | SingletonOverride1#singleton2 | calls.rb:392:5:394:7 | singleton2 | -| calls.rb:397:9:397:18 | call to singleton2 | calls.rb:396:5:398:7 | call_singleton2 | -| calls.rb:397:9:397:18 | self | calls.rb:396:5:398:7 | call_singleton2 | -| calls.rb:403:9:403:43 | call to puts | calls.rb:402:5:404:7 | instance1 | -| calls.rb:403:9:403:43 | self | calls.rb:402:5:404:7 | instance1 | -| calls.rb:403:14:403:43 | "SingletonOverride1#instance1" | calls.rb:402:5:404:7 | instance1 | -| calls.rb:403:15:403:42 | SingletonOverride1#instance1 | calls.rb:402:5:404:7 | instance1 | -| calls.rb:415:13:415:48 | call to puts | calls.rb:414:9:416:11 | singleton1 | -| calls.rb:415:13:415:48 | self | calls.rb:414:9:416:11 | singleton1 | -| calls.rb:415:18:415:48 | "SingletonOverride2#singleton1" | calls.rb:414:9:416:11 | singleton1 | -| calls.rb:415:19:415:47 | SingletonOverride2#singleton1 | calls.rb:414:9:416:11 | singleton1 | -| calls.rb:420:9:420:44 | call to puts | calls.rb:419:5:421:7 | singleton2 | -| calls.rb:420:9:420:44 | self | calls.rb:419:5:421:7 | singleton2 | -| calls.rb:420:14:420:44 | "SingletonOverride2#singleton2" | calls.rb:419:5:421:7 | singleton2 | -| calls.rb:420:15:420:43 | SingletonOverride2#singleton2 | calls.rb:419:5:421:7 | singleton2 | -| calls.rb:424:9:424:43 | call to puts | calls.rb:423:5:425:7 | instance1 | -| calls.rb:424:9:424:43 | self | calls.rb:423:5:425:7 | instance1 | -| calls.rb:424:14:424:43 | "SingletonOverride2#instance1" | calls.rb:423:5:425:7 | instance1 | -| calls.rb:424:15:424:42 | SingletonOverride2#instance1 | calls.rb:423:5:425:7 | instance1 | -| calls.rb:436:13:436:48 | call to puts | calls.rb:435:9:437:11 | m1 | -| calls.rb:436:13:436:48 | self | calls.rb:435:9:437:11 | m1 | -| calls.rb:436:18:436:48 | "ConditionalInstanceMethods#m1" | calls.rb:435:9:437:11 | m1 | -| calls.rb:436:19:436:47 | ConditionalInstanceMethods#m1 | calls.rb:435:9:437:11 | m1 | -| calls.rb:441:9:441:44 | call to puts | calls.rb:440:5:452:7 | m2 | -| calls.rb:441:9:441:44 | self | calls.rb:440:5:452:7 | m2 | -| calls.rb:441:14:441:44 | "ConditionalInstanceMethods#m2" | calls.rb:440:5:452:7 | m2 | -| calls.rb:441:15:441:43 | ConditionalInstanceMethods#m2 | calls.rb:440:5:452:7 | m2 | -| calls.rb:443:9:449:11 | m3 | calls.rb:440:5:452:7 | m2 | -| calls.rb:444:13:444:48 | call to puts | calls.rb:443:9:449:11 | m3 | -| calls.rb:444:13:444:48 | self | calls.rb:443:9:449:11 | m3 | -| calls.rb:444:18:444:48 | "ConditionalInstanceMethods#m3" | calls.rb:443:9:449:11 | m3 | -| calls.rb:444:19:444:47 | ConditionalInstanceMethods#m3 | calls.rb:443:9:449:11 | m3 | -| calls.rb:446:13:448:15 | m4 | calls.rb:443:9:449:11 | m3 | -| calls.rb:447:17:447:52 | call to puts | calls.rb:446:13:448:15 | m4 | -| calls.rb:447:17:447:52 | self | calls.rb:446:13:448:15 | m4 | -| calls.rb:447:22:447:52 | "ConditionalInstanceMethods#m4" | calls.rb:446:13:448:15 | m4 | -| calls.rb:447:23:447:51 | ConditionalInstanceMethods#m4 | calls.rb:446:13:448:15 | m4 | -| calls.rb:451:9:451:10 | call to m3 | calls.rb:440:5:452:7 | m2 | -| calls.rb:451:9:451:10 | self | calls.rb:440:5:452:7 | m2 | -| calls.rb:457:17:457:40 | call to puts | calls.rb:456:13:458:15 | m5 | -| calls.rb:457:17:457:40 | self | calls.rb:456:13:458:15 | m5 | -| calls.rb:457:22:457:40 | "AnonymousClass#m5" | calls.rb:456:13:458:15 | m5 | -| calls.rb:457:23:457:39 | AnonymousClass#m5 | calls.rb:456:13:458:15 | m5 | -| calls.rb:473:13:473:22 | call to puts | calls.rb:472:9:474:11 | foo | -| calls.rb:473:13:473:22 | self | calls.rb:472:9:474:11 | foo | -| calls.rb:473:18:473:22 | "foo" | calls.rb:472:9:474:11 | foo | -| calls.rb:473:19:473:21 | foo | calls.rb:472:9:474:11 | foo | -| calls.rb:479:13:479:22 | call to puts | calls.rb:478:9:480:11 | bar | -| calls.rb:479:13:479:22 | self | calls.rb:478:9:480:11 | bar | -| calls.rb:479:18:479:22 | "bar" | calls.rb:478:9:480:11 | bar | -| calls.rb:479:19:479:21 | bar | calls.rb:478:9:480:11 | bar | -| calls.rb:498:9:498:46 | call to puts | calls.rb:497:5:499:7 | singleton | -| calls.rb:498:9:498:46 | self | calls.rb:497:5:499:7 | singleton | -| calls.rb:498:14:498:46 | "ExtendSingletonMethod#singleton" | calls.rb:497:5:499:7 | singleton | -| calls.rb:498:15:498:45 | ExtendSingletonMethod#singleton | calls.rb:497:5:499:7 | singleton | -| calls.rb:527:9:527:42 | call to puts | calls.rb:526:15:528:7 | foo | -| calls.rb:527:9:527:42 | self | calls.rb:526:15:528:7 | foo | -| calls.rb:527:14:527:42 | "ProtectedMethodInModule#foo" | calls.rb:526:15:528:7 | foo | -| calls.rb:527:15:527:41 | ProtectedMethodInModule#foo | calls.rb:526:15:528:7 | foo | -| calls.rb:535:9:535:35 | call to puts | calls.rb:534:15:536:7 | bar | -| calls.rb:535:9:535:35 | self | calls.rb:534:15:536:7 | bar | -| calls.rb:535:14:535:35 | "ProtectedMethods#bar" | calls.rb:534:15:536:7 | bar | -| calls.rb:535:15:535:34 | ProtectedMethods#bar | calls.rb:534:15:536:7 | bar | -| calls.rb:539:9:539:11 | call to foo | calls.rb:538:5:543:7 | baz | -| calls.rb:539:9:539:11 | self | calls.rb:538:5:543:7 | baz | -| calls.rb:540:9:540:11 | call to bar | calls.rb:538:5:543:7 | baz | -| calls.rb:540:9:540:11 | self | calls.rb:538:5:543:7 | baz | -| calls.rb:541:9:541:24 | ProtectedMethods | calls.rb:538:5:543:7 | baz | -| calls.rb:541:9:541:28 | call to new | calls.rb:538:5:543:7 | baz | -| calls.rb:541:9:541:32 | call to foo | calls.rb:538:5:543:7 | baz | -| calls.rb:542:9:542:24 | ProtectedMethods | calls.rb:538:5:543:7 | baz | -| calls.rb:542:9:542:28 | call to new | calls.rb:538:5:543:7 | baz | -| calls.rb:542:9:542:32 | call to bar | calls.rb:538:5:543:7 | baz | -| calls.rb:552:9:552:11 | call to foo | calls.rb:551:5:554:7 | baz | -| calls.rb:552:9:552:11 | self | calls.rb:551:5:554:7 | baz | -| calls.rb:553:9:553:27 | ProtectedMethodsSub | calls.rb:551:5:554:7 | baz | -| calls.rb:553:9:553:31 | call to new | calls.rb:551:5:554:7 | baz | -| calls.rb:553:9:553:35 | call to foo | calls.rb:551:5:554:7 | baz | -| calls.rb:572:9:572:17 | call to singleton | calls.rb:571:5:574:7 | mid_method | -| calls.rb:572:9:572:17 | self | calls.rb:571:5:574:7 | mid_method | -| calls.rb:573:9:573:18 | call to singleton2 | calls.rb:571:5:574:7 | mid_method | -| calls.rb:573:9:573:18 | self | calls.rb:571:5:574:7 | mid_method | -| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:587:5:589:7 | call_singleton1 | -| calls.rb:588:9:588:18 | self | calls.rb:587:5:589:7 | call_singleton1 | -| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 | -| calls.rb:592:9:592:23 | self | calls.rb:591:5:593:7 | call_call_singleton1 | -| calls.rb:601:9:601:18 | call to singleton1 | calls.rb:600:5:602:7 | call_singleton1 | -| calls.rb:601:9:601:18 | self | calls.rb:600:5:602:7 | call_singleton1 | -| calls.rb:610:9:610:18 | call to singleton1 | calls.rb:609:5:611:7 | call_singleton1 | -| calls.rb:610:9:610:18 | self | calls.rb:609:5:611:7 | call_singleton1 | -| calls.rb:620:9:620:12 | self | calls.rb:619:5:621:7 | foo | -| calls.rb:620:9:620:16 | call to bar | calls.rb:619:5:621:7 | foo | -| calls.rb:629:9:629:13 | super call to bar | calls.rb:628:5:630:7 | bar | -| calls.rb:635:9:635:10 | C1 | calls.rb:634:5:636:7 | new | -| calls.rb:635:9:635:14 | call to new | calls.rb:634:5:636:7 | new | -| calls.rb:643:9:643:12 | self | calls.rb:642:5:644:7 | new | -| calls.rb:643:9:643:21 | call to allocate | calls.rb:642:5:644:7 | new | -| calls.rb:647:9:647:34 | call to puts | calls.rb:646:5:648:7 | instance | -| calls.rb:647:9:647:34 | self | calls.rb:646:5:648:7 | instance | -| calls.rb:647:14:647:34 | "CustomNew2#instance" | calls.rb:646:5:648:7 | instance | -| calls.rb:647:15:647:33 | CustomNew2#instance | calls.rb:646:5:648:7 | instance | +| calls.rb:331:9:331:12 | self | calls.rb:330:5:332:7 | return_self | +| calls.rb:337:9:337:26 | call to puts | calls.rb:336:5:338:7 | instance | +| calls.rb:337:9:337:26 | self | calls.rb:336:5:338:7 | instance | +| calls.rb:337:14:337:26 | "C2#instance" | calls.rb:336:5:338:7 | instance | +| calls.rb:337:15:337:25 | C2#instance | calls.rb:336:5:338:7 | instance | +| calls.rb:343:9:343:26 | call to puts | calls.rb:342:5:344:7 | instance | +| calls.rb:343:9:343:26 | self | calls.rb:342:5:344:7 | instance | +| calls.rb:343:14:343:26 | "C3#instance" | calls.rb:342:5:344:7 | instance | +| calls.rb:343:15:343:25 | C3#instance | calls.rb:342:5:344:7 | instance | +| calls.rb:347:22:347:22 | x | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:347:22:347:22 | x | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:348:5:356:7 | case ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:348:10:348:10 | x | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:349:5:350:18 | when ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:349:10:349:11 | C3 | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:349:12:350:18 | then ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:350:9:350:9 | x | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:350:9:350:18 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:351:5:352:18 | when ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:351:10:351:11 | C2 | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:351:12:352:18 | then ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:352:9:352:9 | x | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:352:9:352:18 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:353:5:354:18 | when ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:353:10:353:11 | C1 | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:353:12:354:18 | then ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:354:9:354:9 | x | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:354:9:354:18 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:355:5:355:8 | else ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:358:5:362:7 | case ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:358:10:358:10 | x | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:359:9:359:29 | in ... then ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:359:12:359:13 | C3 | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:359:15:359:29 | then ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:359:20:359:20 | x | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:359:20:359:29 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:360:9:360:36 | in ... then ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:360:12:360:13 | C2 | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:360:12:360:19 | ... => ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:360:18:360:19 | c2 | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:360:21:360:36 | then ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:360:26:360:27 | c2 | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:360:26:360:36 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:361:9:361:36 | in ... then ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:361:12:361:13 | C1 | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:361:12:361:19 | ... => ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:361:18:361:19 | c1 | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:361:21:361:36 | then ... | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:361:26:361:27 | c1 | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:361:26:361:36 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch | +| calls.rb:374:19:374:19 | x | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:374:19:374:19 | x | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:375:5:377:7 | instance | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:375:9:375:9 | x | calls.rb:374:1:378:3 | add_singleton | +| calls.rb:376:9:376:28 | call to puts | calls.rb:375:5:377:7 | instance | +| calls.rb:376:9:376:28 | self | calls.rb:375:5:377:7 | instance | +| calls.rb:376:14:376:28 | "instance_on x" | calls.rb:375:5:377:7 | instance | +| calls.rb:376:15:376:27 | instance_on x | calls.rb:375:5:377:7 | instance | +| calls.rb:388:13:388:48 | call to puts | calls.rb:387:9:389:11 | singleton1 | +| calls.rb:388:13:388:48 | self | calls.rb:387:9:389:11 | singleton1 | +| calls.rb:388:18:388:48 | "SingletonOverride1#singleton1" | calls.rb:387:9:389:11 | singleton1 | +| calls.rb:388:19:388:47 | SingletonOverride1#singleton1 | calls.rb:387:9:389:11 | singleton1 | +| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:391:9:393:11 | call_singleton1 | +| calls.rb:392:13:392:22 | self | calls.rb:391:9:393:11 | call_singleton1 | +| calls.rb:396:13:396:16 | self | calls.rb:395:9:397:11 | factory | +| calls.rb:396:13:396:20 | call to new | calls.rb:395:9:397:11 | factory | +| calls.rb:396:13:396:30 | call to instance1 | calls.rb:395:9:397:11 | factory | +| calls.rb:401:9:401:44 | call to puts | calls.rb:400:5:402:7 | singleton2 | +| calls.rb:401:9:401:44 | self | calls.rb:400:5:402:7 | singleton2 | +| calls.rb:401:14:401:44 | "SingletonOverride1#singleton2" | calls.rb:400:5:402:7 | singleton2 | +| calls.rb:401:15:401:43 | SingletonOverride1#singleton2 | calls.rb:400:5:402:7 | singleton2 | +| calls.rb:405:9:405:18 | call to singleton2 | calls.rb:404:5:406:7 | call_singleton2 | +| calls.rb:405:9:405:18 | self | calls.rb:404:5:406:7 | call_singleton2 | +| calls.rb:411:9:411:43 | call to puts | calls.rb:410:5:412:7 | instance1 | +| calls.rb:411:9:411:43 | self | calls.rb:410:5:412:7 | instance1 | +| calls.rb:411:14:411:43 | "SingletonOverride1#instance1" | calls.rb:410:5:412:7 | instance1 | +| calls.rb:411:15:411:42 | SingletonOverride1#instance1 | calls.rb:410:5:412:7 | instance1 | +| calls.rb:423:13:423:48 | call to puts | calls.rb:422:9:424:11 | singleton1 | +| calls.rb:423:13:423:48 | self | calls.rb:422:9:424:11 | singleton1 | +| calls.rb:423:18:423:48 | "SingletonOverride2#singleton1" | calls.rb:422:9:424:11 | singleton1 | +| calls.rb:423:19:423:47 | SingletonOverride2#singleton1 | calls.rb:422:9:424:11 | singleton1 | +| calls.rb:428:9:428:44 | call to puts | calls.rb:427:5:429:7 | singleton2 | +| calls.rb:428:9:428:44 | self | calls.rb:427:5:429:7 | singleton2 | +| calls.rb:428:14:428:44 | "SingletonOverride2#singleton2" | calls.rb:427:5:429:7 | singleton2 | +| calls.rb:428:15:428:43 | SingletonOverride2#singleton2 | calls.rb:427:5:429:7 | singleton2 | +| calls.rb:432:9:432:43 | call to puts | calls.rb:431:5:433:7 | instance1 | +| calls.rb:432:9:432:43 | self | calls.rb:431:5:433:7 | instance1 | +| calls.rb:432:14:432:43 | "SingletonOverride2#instance1" | calls.rb:431:5:433:7 | instance1 | +| calls.rb:432:15:432:42 | SingletonOverride2#instance1 | calls.rb:431:5:433:7 | instance1 | +| calls.rb:444:13:444:48 | call to puts | calls.rb:443:9:445:11 | m1 | +| calls.rb:444:13:444:48 | self | calls.rb:443:9:445:11 | m1 | +| calls.rb:444:18:444:48 | "ConditionalInstanceMethods#m1" | calls.rb:443:9:445:11 | m1 | +| calls.rb:444:19:444:47 | ConditionalInstanceMethods#m1 | calls.rb:443:9:445:11 | m1 | +| calls.rb:449:9:449:44 | call to puts | calls.rb:448:5:460:7 | m2 | +| calls.rb:449:9:449:44 | self | calls.rb:448:5:460:7 | m2 | +| calls.rb:449:14:449:44 | "ConditionalInstanceMethods#m2" | calls.rb:448:5:460:7 | m2 | +| calls.rb:449:15:449:43 | ConditionalInstanceMethods#m2 | calls.rb:448:5:460:7 | m2 | +| calls.rb:451:9:457:11 | m3 | calls.rb:448:5:460:7 | m2 | +| calls.rb:452:13:452:48 | call to puts | calls.rb:451:9:457:11 | m3 | +| calls.rb:452:13:452:48 | self | calls.rb:451:9:457:11 | m3 | +| calls.rb:452:18:452:48 | "ConditionalInstanceMethods#m3" | calls.rb:451:9:457:11 | m3 | +| calls.rb:452:19:452:47 | ConditionalInstanceMethods#m3 | calls.rb:451:9:457:11 | m3 | +| calls.rb:454:13:456:15 | m4 | calls.rb:451:9:457:11 | m3 | +| calls.rb:455:17:455:52 | call to puts | calls.rb:454:13:456:15 | m4 | +| calls.rb:455:17:455:52 | self | calls.rb:454:13:456:15 | m4 | +| calls.rb:455:22:455:52 | "ConditionalInstanceMethods#m4" | calls.rb:454:13:456:15 | m4 | +| calls.rb:455:23:455:51 | ConditionalInstanceMethods#m4 | calls.rb:454:13:456:15 | m4 | +| calls.rb:459:9:459:10 | call to m3 | calls.rb:448:5:460:7 | m2 | +| calls.rb:459:9:459:10 | self | calls.rb:448:5:460:7 | m2 | +| calls.rb:465:17:465:40 | call to puts | calls.rb:464:13:466:15 | m5 | +| calls.rb:465:17:465:40 | self | calls.rb:464:13:466:15 | m5 | +| calls.rb:465:22:465:40 | "AnonymousClass#m5" | calls.rb:464:13:466:15 | m5 | +| calls.rb:465:23:465:39 | AnonymousClass#m5 | calls.rb:464:13:466:15 | m5 | +| calls.rb:481:13:481:22 | call to puts | calls.rb:480:9:482:11 | foo | +| calls.rb:481:13:481:22 | self | calls.rb:480:9:482:11 | foo | +| calls.rb:481:18:481:22 | "foo" | calls.rb:480:9:482:11 | foo | +| calls.rb:481:19:481:21 | foo | calls.rb:480:9:482:11 | foo | +| calls.rb:487:13:487:22 | call to puts | calls.rb:486:9:488:11 | bar | +| calls.rb:487:13:487:22 | self | calls.rb:486:9:488:11 | bar | +| calls.rb:487:18:487:22 | "bar" | calls.rb:486:9:488:11 | bar | +| calls.rb:487:19:487:21 | bar | calls.rb:486:9:488:11 | bar | +| calls.rb:506:9:506:46 | call to puts | calls.rb:505:5:507:7 | singleton | +| calls.rb:506:9:506:46 | self | calls.rb:505:5:507:7 | singleton | +| calls.rb:506:14:506:46 | "ExtendSingletonMethod#singleton" | calls.rb:505:5:507:7 | singleton | +| calls.rb:506:15:506:45 | ExtendSingletonMethod#singleton | calls.rb:505:5:507:7 | singleton | +| calls.rb:535:9:535:42 | call to puts | calls.rb:534:15:536:7 | foo | +| calls.rb:535:9:535:42 | self | calls.rb:534:15:536:7 | foo | +| calls.rb:535:14:535:42 | "ProtectedMethodInModule#foo" | calls.rb:534:15:536:7 | foo | +| calls.rb:535:15:535:41 | ProtectedMethodInModule#foo | calls.rb:534:15:536:7 | foo | +| calls.rb:543:9:543:35 | call to puts | calls.rb:542:15:544:7 | bar | +| calls.rb:543:9:543:35 | self | calls.rb:542:15:544:7 | bar | +| calls.rb:543:14:543:35 | "ProtectedMethods#bar" | calls.rb:542:15:544:7 | bar | +| calls.rb:543:15:543:34 | ProtectedMethods#bar | calls.rb:542:15:544:7 | bar | +| calls.rb:547:9:547:11 | call to foo | calls.rb:546:5:551:7 | baz | +| calls.rb:547:9:547:11 | self | calls.rb:546:5:551:7 | baz | +| calls.rb:548:9:548:11 | call to bar | calls.rb:546:5:551:7 | baz | +| calls.rb:548:9:548:11 | self | calls.rb:546:5:551:7 | baz | +| calls.rb:549:9:549:24 | ProtectedMethods | calls.rb:546:5:551:7 | baz | +| calls.rb:549:9:549:28 | call to new | calls.rb:546:5:551:7 | baz | +| calls.rb:549:9:549:32 | call to foo | calls.rb:546:5:551:7 | baz | +| calls.rb:550:9:550:24 | ProtectedMethods | calls.rb:546:5:551:7 | baz | +| calls.rb:550:9:550:28 | call to new | calls.rb:546:5:551:7 | baz | +| calls.rb:550:9:550:32 | call to bar | calls.rb:546:5:551:7 | baz | +| calls.rb:560:9:560:11 | call to foo | calls.rb:559:5:562:7 | baz | +| calls.rb:560:9:560:11 | self | calls.rb:559:5:562:7 | baz | +| calls.rb:561:9:561:27 | ProtectedMethodsSub | calls.rb:559:5:562:7 | baz | +| calls.rb:561:9:561:31 | call to new | calls.rb:559:5:562:7 | baz | +| calls.rb:561:9:561:35 | call to foo | calls.rb:559:5:562:7 | baz | +| calls.rb:580:9:580:17 | call to singleton | calls.rb:579:5:582:7 | mid_method | +| calls.rb:580:9:580:17 | self | calls.rb:579:5:582:7 | mid_method | +| calls.rb:581:9:581:18 | call to singleton2 | calls.rb:579:5:582:7 | mid_method | +| calls.rb:581:9:581:18 | self | calls.rb:579:5:582:7 | mid_method | +| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:595:5:597:7 | call_singleton1 | +| calls.rb:596:9:596:18 | self | calls.rb:595:5:597:7 | call_singleton1 | +| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 | +| calls.rb:600:9:600:23 | self | calls.rb:599:5:601:7 | call_call_singleton1 | +| calls.rb:609:9:609:18 | call to singleton1 | calls.rb:608:5:610:7 | call_singleton1 | +| calls.rb:609:9:609:18 | self | calls.rb:608:5:610:7 | call_singleton1 | +| calls.rb:618:9:618:18 | call to singleton1 | calls.rb:617:5:619:7 | call_singleton1 | +| calls.rb:618:9:618:18 | self | calls.rb:617:5:619:7 | call_singleton1 | +| calls.rb:628:9:628:12 | self | calls.rb:627:5:629:7 | foo | +| calls.rb:628:9:628:16 | call to bar | calls.rb:627:5:629:7 | foo | +| calls.rb:637:9:637:13 | super call to bar | calls.rb:636:5:638:7 | bar | +| calls.rb:643:9:643:10 | C1 | calls.rb:642:5:644:7 | new | +| calls.rb:643:9:643:14 | call to new | calls.rb:642:5:644:7 | new | +| calls.rb:651:9:651:12 | self | calls.rb:650:5:652:7 | new | +| calls.rb:651:9:651:21 | call to allocate | calls.rb:650:5:652:7 | new | +| calls.rb:655:9:655:34 | call to puts | calls.rb:654:5:656:7 | instance | +| calls.rb:655:9:655:34 | self | calls.rb:654:5:656:7 | instance | +| calls.rb:655:14:655:34 | "CustomNew2#instance" | calls.rb:654:5:656:7 | instance | +| calls.rb:655:15:655:33 | CustomNew2#instance | calls.rb:654:5:656:7 | instance | +| calls.rb:661:23:661:23 | x | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:661:23:661:23 | x | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:662:5:662:11 | Array | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:662:5:662:11 | [...] | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:662:5:662:11 | call to [] | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:662:5:664:7 | call to each | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:662:6:662:6 | 0 | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:662:8:662:8 | 1 | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:662:10:662:10 | 2 | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:662:18:664:7 | do ... end | calls.rb:661:1:665:3 | capture_parameter | +| calls.rb:663:9:663:9 | x | calls.rb:661:1:665:3 | capture_parameter | | hello.rb:3:9:3:22 | return | hello.rb:2:5:4:7 | hello | | hello.rb:3:16:3:22 | "hello" | hello.rb:2:5:4:7 | hello | | hello.rb:3:17:3:21 | hello | hello.rb:2:5:4:7 | hello | diff --git a/ruby/ql/test/library-tests/modules/modules.expected b/ruby/ql/test/library-tests/modules/modules.expected index e138f5ce4c3..0b98c128eb0 100644 --- a/ruby/ql/test/library-tests/modules/modules.expected +++ b/ruby/ql/test/library-tests/modules/modules.expected @@ -14,28 +14,28 @@ getModule | calls.rb:176:1:179:3 | B | | calls.rb:190:1:226:3 | Singletons | | calls.rb:310:1:321:3 | SelfNew | -| calls.rb:325:1:329:3 | C1 | -| calls.rb:331:1:335:3 | C2 | -| calls.rb:337:1:341:3 | C3 | -| calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:506:1:508:3 | ExtendSingletonMethod2 | -| calls.rb:512:1:513:3 | ExtendSingletonMethod3 | -| calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | -| calls.rb:583:1:594:3 | SingletonA | -| calls.rb:596:1:603:3 | SingletonB | -| calls.rb:605:1:612:3 | SingletonC | -| calls.rb:618:1:624:3 | Included | -| calls.rb:626:1:631:3 | IncludesIncluded | -| calls.rb:633:1:637:3 | CustomNew1 | -| calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:325:1:333:3 | C1 | +| calls.rb:335:1:339:3 | C2 | +| calls.rb:341:1:345:3 | C3 | +| calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:504:1:510:3 | ExtendSingletonMethod | +| calls.rb:514:1:516:3 | ExtendSingletonMethod2 | +| calls.rb:520:1:521:3 | ExtendSingletonMethod3 | +| calls.rb:533:1:537:3 | ProtectedMethodInModule | +| calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | +| calls.rb:591:1:602:3 | SingletonA | +| calls.rb:604:1:611:3 | SingletonB | +| calls.rb:613:1:620:3 | SingletonC | +| calls.rb:626:1:632:3 | Included | +| calls.rb:634:1:639:3 | IncludesIncluded | +| calls.rb:641:1:645:3 | CustomNew1 | +| calls.rb:649:1:657:3 | CustomNew2 | | file://:0:0:0:0 | BasicObject | | file://:0:0:0:0 | Class | | file://:0:0:0:0 | Complex | @@ -111,7 +111,7 @@ getADeclaration | calls.rb:96:1:98:3 | String | calls.rb:96:1:98:3 | String | | calls.rb:100:1:103:3 | Kernel | calls.rb:100:1:103:3 | Kernel | | calls.rb:105:1:113:3 | Module | calls.rb:105:1:113:3 | Module | -| calls.rb:115:1:118:3 | Object | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:115:1:118:3 | Object | calls.rb:1:1:667:52 | calls.rb | | calls.rb:115:1:118:3 | Object | calls.rb:115:1:118:3 | Object | | calls.rb:115:1:118:3 | Object | hello.rb:1:1:22:3 | hello.rb | | calls.rb:115:1:118:3 | Object | instance_fields.rb:1:1:29:4 | instance_fields.rb | @@ -131,28 +131,28 @@ getADeclaration | calls.rb:176:1:179:3 | B | instance_fields.rb:16:1:25:3 | B | | calls.rb:190:1:226:3 | Singletons | calls.rb:190:1:226:3 | Singletons | | calls.rb:310:1:321:3 | SelfNew | calls.rb:310:1:321:3 | SelfNew | -| calls.rb:325:1:329:3 | C1 | calls.rb:325:1:329:3 | C1 | -| calls.rb:331:1:335:3 | C2 | calls.rb:331:1:335:3 | C2 | -| calls.rb:337:1:341:3 | C3 | calls.rb:337:1:341:3 | C3 | -| calls.rb:377:1:405:3 | SingletonOverride1 | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:412:1:426:3 | SingletonOverride2 | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:496:1:502:3 | ExtendSingletonMethod | calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:506:1:508:3 | ExtendSingletonMethod2 | calls.rb:506:1:508:3 | ExtendSingletonMethod2 | -| calls.rb:512:1:513:3 | ExtendSingletonMethod3 | calls.rb:512:1:513:3 | ExtendSingletonMethod3 | -| calls.rb:525:1:529:3 | ProtectedMethodInModule | calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:531:1:544:3 | ProtectedMethods | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | calls.rb:550:1:555:3 | ProtectedMethodsSub | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | calls.rb:564:1:567:3 | SingletonUpCall_Base | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | calls.rb:576:1:581:3 | SingletonUpCall_SubSub | -| calls.rb:583:1:594:3 | SingletonA | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:596:1:603:3 | SingletonB | calls.rb:596:1:603:3 | SingletonB | -| calls.rb:605:1:612:3 | SingletonC | calls.rb:605:1:612:3 | SingletonC | -| calls.rb:618:1:624:3 | Included | calls.rb:618:1:624:3 | Included | -| calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:626:1:631:3 | IncludesIncluded | -| calls.rb:633:1:637:3 | CustomNew1 | calls.rb:633:1:637:3 | CustomNew1 | -| calls.rb:641:1:649:3 | CustomNew2 | calls.rb:641:1:649:3 | CustomNew2 | +| calls.rb:325:1:333:3 | C1 | calls.rb:325:1:333:3 | C1 | +| calls.rb:335:1:339:3 | C2 | calls.rb:335:1:339:3 | C2 | +| calls.rb:341:1:345:3 | C3 | calls.rb:341:1:345:3 | C3 | +| calls.rb:385:1:413:3 | SingletonOverride1 | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:420:1:434:3 | SingletonOverride2 | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:504:1:510:3 | ExtendSingletonMethod | calls.rb:504:1:510:3 | ExtendSingletonMethod | +| calls.rb:514:1:516:3 | ExtendSingletonMethod2 | calls.rb:514:1:516:3 | ExtendSingletonMethod2 | +| calls.rb:520:1:521:3 | ExtendSingletonMethod3 | calls.rb:520:1:521:3 | ExtendSingletonMethod3 | +| calls.rb:533:1:537:3 | ProtectedMethodInModule | calls.rb:533:1:537:3 | ProtectedMethodInModule | +| calls.rb:539:1:552:3 | ProtectedMethods | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | calls.rb:558:1:563:3 | ProtectedMethodsSub | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | calls.rb:572:1:575:3 | SingletonUpCall_Base | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | calls.rb:584:1:589:3 | SingletonUpCall_SubSub | +| calls.rb:591:1:602:3 | SingletonA | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:604:1:611:3 | SingletonB | calls.rb:604:1:611:3 | SingletonB | +| calls.rb:613:1:620:3 | SingletonC | calls.rb:613:1:620:3 | SingletonC | +| calls.rb:626:1:632:3 | Included | calls.rb:626:1:632:3 | Included | +| calls.rb:634:1:639:3 | IncludesIncluded | calls.rb:634:1:639:3 | IncludesIncluded | +| calls.rb:641:1:645:3 | CustomNew1 | calls.rb:641:1:645:3 | CustomNew1 | +| calls.rb:649:1:657:3 | CustomNew2 | calls.rb:649:1:657:3 | CustomNew2 | | hello.rb:1:1:8:3 | EnglishWords | hello.rb:1:1:8:3 | EnglishWords | | hello.rb:11:1:16:3 | Greeting | hello.rb:11:1:16:3 | Greeting | | hello.rb:18:1:22:3 | HelloWorld | hello.rb:18:1:22:3 | HelloWorld | @@ -221,23 +221,23 @@ getSuperClass | calls.rb:176:1:179:3 | B | calls.rb:165:1:169:3 | S | | calls.rb:190:1:226:3 | Singletons | calls.rb:115:1:118:3 | Object | | calls.rb:310:1:321:3 | SelfNew | calls.rb:115:1:118:3 | Object | -| calls.rb:325:1:329:3 | C1 | calls.rb:115:1:118:3 | Object | -| calls.rb:331:1:335:3 | C2 | calls.rb:325:1:329:3 | C1 | -| calls.rb:337:1:341:3 | C3 | calls.rb:331:1:335:3 | C2 | -| calls.rb:377:1:405:3 | SingletonOverride1 | calls.rb:115:1:118:3 | Object | -| calls.rb:412:1:426:3 | SingletonOverride2 | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | calls.rb:115:1:118:3 | Object | -| calls.rb:531:1:544:3 | ProtectedMethods | calls.rb:115:1:118:3 | Object | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | calls.rb:115:1:118:3 | Object | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | calls.rb:564:1:567:3 | SingletonUpCall_Base | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:583:1:594:3 | SingletonA | calls.rb:115:1:118:3 | Object | -| calls.rb:596:1:603:3 | SingletonB | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:605:1:612:3 | SingletonC | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:115:1:118:3 | Object | -| calls.rb:633:1:637:3 | CustomNew1 | calls.rb:115:1:118:3 | Object | -| calls.rb:641:1:649:3 | CustomNew2 | calls.rb:115:1:118:3 | Object | +| calls.rb:325:1:333:3 | C1 | calls.rb:115:1:118:3 | Object | +| calls.rb:335:1:339:3 | C2 | calls.rb:325:1:333:3 | C1 | +| calls.rb:341:1:345:3 | C3 | calls.rb:335:1:339:3 | C2 | +| calls.rb:385:1:413:3 | SingletonOverride1 | calls.rb:115:1:118:3 | Object | +| calls.rb:420:1:434:3 | SingletonOverride2 | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | calls.rb:115:1:118:3 | Object | +| calls.rb:539:1:552:3 | ProtectedMethods | calls.rb:115:1:118:3 | Object | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | calls.rb:115:1:118:3 | Object | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | calls.rb:572:1:575:3 | SingletonUpCall_Base | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:591:1:602:3 | SingletonA | calls.rb:115:1:118:3 | Object | +| calls.rb:604:1:611:3 | SingletonB | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:613:1:620:3 | SingletonC | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:634:1:639:3 | IncludesIncluded | calls.rb:115:1:118:3 | Object | +| calls.rb:641:1:645:3 | CustomNew1 | calls.rb:115:1:118:3 | Object | +| calls.rb:649:1:657:3 | CustomNew2 | calls.rb:115:1:118:3 | Object | | file://:0:0:0:0 | Class | calls.rb:105:1:113:3 | Module | | file://:0:0:0:0 | Complex | file://:0:0:0:0 | Numeric | | file://:0:0:0:0 | FalseClass | calls.rb:115:1:118:3 | Object | @@ -278,8 +278,8 @@ getAPrependedModule getAnIncludedModule | calls.rb:43:1:58:3 | C | calls.rb:21:1:34:3 | M | | calls.rb:115:1:118:3 | Object | calls.rb:100:1:103:3 | Kernel | -| calls.rb:531:1:544:3 | ProtectedMethods | calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:618:1:624:3 | Included | +| calls.rb:539:1:552:3 | ProtectedMethods | calls.rb:533:1:537:3 | ProtectedMethodInModule | +| calls.rb:634:1:639:3 | IncludesIncluded | calls.rb:626:1:632:3 | Included | | hello.rb:11:1:16:3 | Greeting | hello.rb:1:1:8:3 | EnglishWords | | modules.rb:88:1:93:3 | IncludeTest | modules.rb:63:1:81:3 | Test | | modules.rb:95:1:99:3 | IncludeTest2 | modules.rb:63:1:81:3 | Test | @@ -316,76 +316,79 @@ resolveConstantReadAccess | calls.rb:302:10:302:19 | Singletons | Singletons | | calls.rb:308:1:308:10 | Singletons | Singletons | | calls.rb:323:1:323:7 | SelfNew | SelfNew | -| calls.rb:331:12:331:13 | C1 | C1 | -| calls.rb:337:12:337:13 | C2 | C2 | -| calls.rb:345:10:345:11 | C3 | C3 | -| calls.rb:347:10:347:11 | C2 | C2 | -| calls.rb:349:10:349:11 | C1 | C1 | -| calls.rb:355:12:355:13 | C3 | C3 | -| calls.rb:356:12:356:13 | C2 | C2 | -| calls.rb:357:12:357:13 | C1 | C1 | -| calls.rb:361:6:361:7 | C1 | C1 | -| calls.rb:363:19:363:20 | C1 | C1 | -| calls.rb:364:19:364:20 | C2 | C2 | -| calls.rb:365:19:365:20 | C3 | C3 | -| calls.rb:373:6:373:7 | C1 | C1 | -| calls.rb:407:1:407:18 | SingletonOverride1 | SingletonOverride1 | -| calls.rb:408:1:408:18 | SingletonOverride1 | SingletonOverride1 | -| calls.rb:409:1:409:18 | SingletonOverride1 | SingletonOverride1 | -| calls.rb:410:1:410:18 | SingletonOverride1 | SingletonOverride1 | -| calls.rb:412:28:412:45 | SingletonOverride1 | SingletonOverride1 | -| calls.rb:428:1:428:18 | SingletonOverride2 | SingletonOverride2 | -| calls.rb:429:1:429:18 | SingletonOverride2 | SingletonOverride2 | -| calls.rb:430:1:430:18 | SingletonOverride2 | SingletonOverride2 | -| calls.rb:431:1:431:18 | SingletonOverride2 | SingletonOverride2 | -| calls.rb:455:9:455:13 | Class | Class | -| calls.rb:463:1:463:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:464:1:464:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:465:1:465:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:466:1:466:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:467:1:467:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:468:1:468:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:470:27:470:31 | Class | Class | -| calls.rb:471:5:471:11 | Array | Array | -| calls.rb:477:5:477:9 | Class | Class | -| calls.rb:483:5:483:11 | Array | Array | -| calls.rb:490:1:490:23 | EsotericInstanceMethods | EsotericInstanceMethods | -| calls.rb:491:1:491:23 | EsotericInstanceMethods | EsotericInstanceMethods | -| calls.rb:492:1:492:23 | EsotericInstanceMethods | EsotericInstanceMethods | -| calls.rb:493:1:493:23 | EsotericInstanceMethods | EsotericInstanceMethods | -| calls.rb:494:1:494:23 | EsotericInstanceMethods | EsotericInstanceMethods | -| calls.rb:504:1:504:21 | ExtendSingletonMethod | ExtendSingletonMethod | -| calls.rb:507:12:507:32 | ExtendSingletonMethod | ExtendSingletonMethod | -| calls.rb:510:1:510:22 | ExtendSingletonMethod2 | ExtendSingletonMethod2 | -| calls.rb:515:1:515:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | -| calls.rb:515:31:515:51 | ExtendSingletonMethod | ExtendSingletonMethod | -| calls.rb:517:1:517:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | -| calls.rb:521:12:521:32 | ExtendSingletonMethod | ExtendSingletonMethod | -| calls.rb:532:13:532:35 | ProtectedMethodInModule | ProtectedMethodInModule | -| calls.rb:541:9:541:24 | ProtectedMethods | ProtectedMethods | -| calls.rb:542:9:542:24 | ProtectedMethods | ProtectedMethods | -| calls.rb:546:1:546:16 | ProtectedMethods | ProtectedMethods | -| calls.rb:547:1:547:16 | ProtectedMethods | ProtectedMethods | -| calls.rb:548:1:548:16 | ProtectedMethods | ProtectedMethods | -| calls.rb:550:29:550:44 | ProtectedMethods | ProtectedMethods | -| calls.rb:553:9:553:27 | ProtectedMethodsSub | ProtectedMethodsSub | -| calls.rb:557:1:557:19 | ProtectedMethodsSub | ProtectedMethodsSub | -| calls.rb:558:1:558:19 | ProtectedMethodsSub | ProtectedMethodsSub | -| calls.rb:559:1:559:19 | ProtectedMethodsSub | ProtectedMethodsSub | -| calls.rb:561:1:561:7 | Array | Array | -| calls.rb:561:2:561:2 | C | C | -| calls.rb:562:1:562:13 | Array | Array | -| calls.rb:568:29:568:48 | SingletonUpCall_Base | SingletonUpCall_Base | -| calls.rb:576:32:576:50 | SingletonUpCall_Sub | SingletonUpCall_Sub | -| calls.rb:596:20:596:29 | SingletonA | SingletonA | -| calls.rb:605:20:605:29 | SingletonA | SingletonA | -| calls.rb:614:1:614:10 | SingletonA | SingletonA | -| calls.rb:615:1:615:10 | SingletonB | SingletonB | -| calls.rb:616:1:616:10 | SingletonC | SingletonC | -| calls.rb:627:13:627:20 | Included | Included | -| calls.rb:635:9:635:10 | C1 | C1 | -| calls.rb:639:1:639:10 | CustomNew1 | CustomNew1 | -| calls.rb:651:1:651:10 | CustomNew2 | CustomNew2 | +| calls.rb:335:12:335:13 | C1 | C1 | +| calls.rb:341:12:341:13 | C2 | C2 | +| calls.rb:349:10:349:11 | C3 | C3 | +| calls.rb:351:10:351:11 | C2 | C2 | +| calls.rb:353:10:353:11 | C1 | C1 | +| calls.rb:359:12:359:13 | C3 | C3 | +| calls.rb:360:12:360:13 | C2 | C2 | +| calls.rb:361:12:361:13 | C1 | C1 | +| calls.rb:365:6:365:7 | C1 | C1 | +| calls.rb:368:19:368:20 | C1 | C1 | +| calls.rb:369:19:369:20 | C2 | C2 | +| calls.rb:370:19:370:20 | C3 | C3 | +| calls.rb:372:1:372:2 | C3 | C3 | +| calls.rb:380:6:380:7 | C1 | C1 | +| calls.rb:415:1:415:18 | SingletonOverride1 | SingletonOverride1 | +| calls.rb:416:1:416:18 | SingletonOverride1 | SingletonOverride1 | +| calls.rb:417:1:417:18 | SingletonOverride1 | SingletonOverride1 | +| calls.rb:418:1:418:18 | SingletonOverride1 | SingletonOverride1 | +| calls.rb:420:28:420:45 | SingletonOverride1 | SingletonOverride1 | +| calls.rb:436:1:436:18 | SingletonOverride2 | SingletonOverride2 | +| calls.rb:437:1:437:18 | SingletonOverride2 | SingletonOverride2 | +| calls.rb:438:1:438:18 | SingletonOverride2 | SingletonOverride2 | +| calls.rb:439:1:439:18 | SingletonOverride2 | SingletonOverride2 | +| calls.rb:463:9:463:13 | Class | Class | +| calls.rb:471:1:471:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:472:1:472:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:473:1:473:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:474:1:474:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:475:1:475:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:476:1:476:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:478:27:478:31 | Class | Class | +| calls.rb:479:5:479:11 | Array | Array | +| calls.rb:485:5:485:9 | Class | Class | +| calls.rb:491:5:491:11 | Array | Array | +| calls.rb:498:1:498:23 | EsotericInstanceMethods | EsotericInstanceMethods | +| calls.rb:499:1:499:23 | EsotericInstanceMethods | EsotericInstanceMethods | +| calls.rb:500:1:500:23 | EsotericInstanceMethods | EsotericInstanceMethods | +| calls.rb:501:1:501:23 | EsotericInstanceMethods | EsotericInstanceMethods | +| calls.rb:502:1:502:23 | EsotericInstanceMethods | EsotericInstanceMethods | +| calls.rb:512:1:512:21 | ExtendSingletonMethod | ExtendSingletonMethod | +| calls.rb:515:12:515:32 | ExtendSingletonMethod | ExtendSingletonMethod | +| calls.rb:518:1:518:22 | ExtendSingletonMethod2 | ExtendSingletonMethod2 | +| calls.rb:523:1:523:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | +| calls.rb:523:31:523:51 | ExtendSingletonMethod | ExtendSingletonMethod | +| calls.rb:525:1:525:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | +| calls.rb:529:12:529:32 | ExtendSingletonMethod | ExtendSingletonMethod | +| calls.rb:540:13:540:35 | ProtectedMethodInModule | ProtectedMethodInModule | +| calls.rb:549:9:549:24 | ProtectedMethods | ProtectedMethods | +| calls.rb:550:9:550:24 | ProtectedMethods | ProtectedMethods | +| calls.rb:554:1:554:16 | ProtectedMethods | ProtectedMethods | +| calls.rb:555:1:555:16 | ProtectedMethods | ProtectedMethods | +| calls.rb:556:1:556:16 | ProtectedMethods | ProtectedMethods | +| calls.rb:558:29:558:44 | ProtectedMethods | ProtectedMethods | +| calls.rb:561:9:561:27 | ProtectedMethodsSub | ProtectedMethodsSub | +| calls.rb:565:1:565:19 | ProtectedMethodsSub | ProtectedMethodsSub | +| calls.rb:566:1:566:19 | ProtectedMethodsSub | ProtectedMethodsSub | +| calls.rb:567:1:567:19 | ProtectedMethodsSub | ProtectedMethodsSub | +| calls.rb:569:1:569:7 | Array | Array | +| calls.rb:569:2:569:2 | C | C | +| calls.rb:570:1:570:13 | Array | Array | +| calls.rb:576:29:576:48 | SingletonUpCall_Base | SingletonUpCall_Base | +| calls.rb:584:32:584:50 | SingletonUpCall_Sub | SingletonUpCall_Sub | +| calls.rb:604:20:604:29 | SingletonA | SingletonA | +| calls.rb:613:20:613:29 | SingletonA | SingletonA | +| calls.rb:622:1:622:10 | SingletonA | SingletonA | +| calls.rb:623:1:623:10 | SingletonB | SingletonB | +| calls.rb:624:1:624:10 | SingletonC | SingletonC | +| calls.rb:635:13:635:20 | Included | Included | +| calls.rb:643:9:643:10 | C1 | C1 | +| calls.rb:647:1:647:10 | CustomNew1 | CustomNew1 | +| calls.rb:659:1:659:10 | CustomNew2 | CustomNew2 | +| calls.rb:662:5:662:11 | Array | Array | +| calls.rb:667:20:667:21 | C1 | C1 | | hello.rb:12:13:12:24 | EnglishWords | EnglishWords | | hello.rb:18:20:18:27 | Greeting | Greeting | | instance_fields.rb:4:22:4:31 | A_target | A_target | @@ -469,29 +472,29 @@ resolveConstantWriteAccess | calls.rb:176:1:179:3 | B | B | | calls.rb:190:1:226:3 | Singletons | Singletons | | calls.rb:310:1:321:3 | SelfNew | SelfNew | -| calls.rb:325:1:329:3 | C1 | C1 | -| calls.rb:331:1:335:3 | C2 | C2 | -| calls.rb:337:1:341:3 | C3 | C3 | -| calls.rb:377:1:405:3 | SingletonOverride1 | SingletonOverride1 | -| calls.rb:412:1:426:3 | SingletonOverride2 | SingletonOverride2 | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:470:1:470:23 | EsotericInstanceMethods | EsotericInstanceMethods | -| calls.rb:496:1:502:3 | ExtendSingletonMethod | ExtendSingletonMethod | -| calls.rb:506:1:508:3 | ExtendSingletonMethod2 | ExtendSingletonMethod2 | -| calls.rb:512:1:513:3 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | -| calls.rb:525:1:529:3 | ProtectedMethodInModule | ProtectedMethodInModule | -| calls.rb:531:1:544:3 | ProtectedMethods | ProtectedMethods | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | ProtectedMethodsSub | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | SingletonUpCall_Base | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | SingletonUpCall_Sub | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | SingletonUpCall_SubSub | -| calls.rb:583:1:594:3 | SingletonA | SingletonA | -| calls.rb:596:1:603:3 | SingletonB | SingletonB | -| calls.rb:605:1:612:3 | SingletonC | SingletonC | -| calls.rb:618:1:624:3 | Included | Included | -| calls.rb:626:1:631:3 | IncludesIncluded | IncludesIncluded | -| calls.rb:633:1:637:3 | CustomNew1 | CustomNew1 | -| calls.rb:641:1:649:3 | CustomNew2 | CustomNew2 | +| calls.rb:325:1:333:3 | C1 | C1 | +| calls.rb:335:1:339:3 | C2 | C2 | +| calls.rb:341:1:345:3 | C3 | C3 | +| calls.rb:385:1:413:3 | SingletonOverride1 | SingletonOverride1 | +| calls.rb:420:1:434:3 | SingletonOverride2 | SingletonOverride2 | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:478:1:478:23 | EsotericInstanceMethods | EsotericInstanceMethods | +| calls.rb:504:1:510:3 | ExtendSingletonMethod | ExtendSingletonMethod | +| calls.rb:514:1:516:3 | ExtendSingletonMethod2 | ExtendSingletonMethod2 | +| calls.rb:520:1:521:3 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | +| calls.rb:533:1:537:3 | ProtectedMethodInModule | ProtectedMethodInModule | +| calls.rb:539:1:552:3 | ProtectedMethods | ProtectedMethods | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | ProtectedMethodsSub | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | SingletonUpCall_Base | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | SingletonUpCall_Sub | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | SingletonUpCall_SubSub | +| calls.rb:591:1:602:3 | SingletonA | SingletonA | +| calls.rb:604:1:611:3 | SingletonB | SingletonB | +| calls.rb:613:1:620:3 | SingletonC | SingletonC | +| calls.rb:626:1:632:3 | Included | Included | +| calls.rb:634:1:639:3 | IncludesIncluded | IncludesIncluded | +| calls.rb:641:1:645:3 | CustomNew1 | CustomNew1 | +| calls.rb:649:1:657:3 | CustomNew2 | CustomNew2 | | hello.rb:1:1:8:3 | EnglishWords | EnglishWords | | hello.rb:11:1:16:3 | Greeting | Greeting | | hello.rb:18:1:22:3 | HelloWorld | HelloWorld | @@ -561,32 +564,32 @@ resolveConstantWriteAccess | unresolved_subclass.rb:17:1:18:3 | Subclass2 | UnresolvedNamespace::X1::X2::X3::Subclass2 | | unresolved_subclass.rb:21:1:22:3 | A | UnresolvedNamespace::X1::X2::X3::A | enclosingModule -| calls.rb:1:1:3:3 | foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:2:5:2:14 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:2:10:2:14 | "foo" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:2:11:2:13 | foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:5:1:5:3 | call to foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:5:1:5:3 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:7:1:9:3 | bar | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:7:5:7:8 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:8:5:8:15 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:8:5:8:15 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:8:10:8:15 | "bar1" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:8:11:8:14 | bar1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:11:1:11:4 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:11:1:11:8 | call to bar | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:13:1:15:3 | bar | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:13:5:13:8 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:14:5:14:15 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:14:5:14:15 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:14:10:14:15 | "bar2" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:14:11:14:14 | bar2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:17:1:17:4 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:17:1:17:8 | call to bar | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:19:1:19:4 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:19:1:19:8 | call to foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:21:1:34:3 | M | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:1:1:3:3 | foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:2:5:2:14 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:2:10:2:14 | "foo" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:2:11:2:13 | foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:5:1:5:3 | call to foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:5:1:5:3 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:7:1:9:3 | bar | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:7:5:7:8 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:8:5:8:15 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:8:5:8:15 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:8:10:8:15 | "bar1" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:8:11:8:14 | bar1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:11:1:11:4 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:11:1:11:8 | call to bar | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:13:1:15:3 | bar | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:13:5:13:8 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:14:5:14:15 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:14:5:14:15 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:14:10:14:15 | "bar2" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:14:11:14:14 | bar2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:17:1:17:4 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:17:1:17:8 | call to bar | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:19:1:19:4 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:19:1:19:8 | call to foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:21:1:34:3 | M | calls.rb:1:1:667:52 | calls.rb | | calls.rb:22:5:24:7 | instance_m | calls.rb:21:1:34:3 | M | | calls.rb:23:9:23:19 | call to singleton_m | calls.rb:21:1:34:3 | M | | calls.rb:23:9:23:19 | self | calls.rb:21:1:34:3 | M | @@ -602,14 +605,14 @@ enclosingModule | calls.rb:32:5:32:15 | self | calls.rb:21:1:34:3 | M | | calls.rb:33:5:33:8 | self | calls.rb:21:1:34:3 | M | | calls.rb:33:5:33:20 | call to singleton_m | calls.rb:21:1:34:3 | M | -| calls.rb:36:1:36:1 | M | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:36:1:36:12 | call to instance_m | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:37:1:37:1 | M | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:37:1:37:13 | call to singleton_m | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:39:1:41:3 | call_instance_m | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:40:5:40:14 | call to instance_m | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:40:5:40:14 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:43:1:58:3 | C | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:36:1:36:1 | M | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:36:1:36:12 | call to instance_m | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:37:1:37:1 | M | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:37:1:37:13 | call to singleton_m | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:39:1:41:3 | call_instance_m | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:40:5:40:14 | call to instance_m | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:40:5:40:14 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:43:1:58:3 | C | calls.rb:1:1:667:52 | calls.rb | | calls.rb:44:5:44:13 | call to include | calls.rb:43:1:58:3 | C | | calls.rb:44:5:44:13 | self | calls.rb:43:1:58:3 | C | | calls.rb:44:13:44:13 | M | calls.rb:43:1:58:3 | C | @@ -630,66 +633,66 @@ enclosingModule | calls.rb:55:9:55:19 | self | calls.rb:43:1:58:3 | C | | calls.rb:56:9:56:12 | self | calls.rb:43:1:58:3 | C | | calls.rb:56:9:56:24 | call to singleton_m | calls.rb:43:1:58:3 | C | -| calls.rb:60:1:60:1 | c | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:60:1:60:9 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:60:5:60:5 | C | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:60:5:60:9 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:61:1:61:1 | c | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:61:1:61:5 | call to baz | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:62:1:62:1 | c | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:62:1:62:13 | call to singleton_m | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:63:1:63:1 | c | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:63:1:63:12 | call to instance_m | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:65:1:69:3 | D | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:65:11:65:11 | C | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:60:1:60:1 | c | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:60:1:60:9 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:60:5:60:5 | C | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:60:5:60:9 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:61:1:61:1 | c | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:61:1:61:5 | call to baz | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:62:1:62:1 | c | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:62:1:62:13 | call to singleton_m | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:63:1:63:1 | c | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:63:1:63:12 | call to instance_m | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:65:1:69:3 | D | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:65:11:65:11 | C | calls.rb:1:1:667:52 | calls.rb | | calls.rb:66:5:68:7 | baz | calls.rb:65:1:69:3 | D | | calls.rb:67:9:67:13 | super call to baz | calls.rb:65:1:69:3 | D | -| calls.rb:71:1:71:1 | d | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:71:1:71:9 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:71:5:71:5 | D | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:71:5:71:9 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:72:1:72:1 | d | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:72:1:72:5 | call to baz | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:73:1:73:1 | d | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:73:1:73:13 | call to singleton_m | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:74:1:74:1 | d | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:74:1:74:12 | call to instance_m | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:76:1:79:3 | optional_arg | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:76:18:76:18 | a | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:76:18:76:18 | a | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:76:22:76:22 | 4 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:76:25:76:25 | b | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:76:25:76:25 | b | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:76:28:76:28 | 5 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:77:5:77:5 | a | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:77:5:77:16 | call to bit_length | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:78:5:78:5 | b | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:78:5:78:16 | call to bit_length | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:81:1:83:3 | call_block | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:82:5:82:11 | yield ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:82:11:82:11 | 1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:85:1:89:3 | foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:86:5:86:7 | var | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:86:5:86:18 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:86:11:86:14 | Hash | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:86:11:86:18 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:87:5:87:7 | var | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:87:5:87:10 | ...[...] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:87:9:87:9 | 1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:88:5:88:29 | call to call_block | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:88:5:88:29 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:88:16:88:29 | { ... } | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:88:19:88:19 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:88:19:88:19 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:88:22:88:24 | var | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:88:22:88:27 | ...[...] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:88:26:88:26 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:91:1:94:3 | Integer | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:71:1:71:1 | d | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:71:1:71:9 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:71:5:71:5 | D | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:71:5:71:9 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:72:1:72:1 | d | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:72:1:72:5 | call to baz | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:73:1:73:1 | d | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:73:1:73:13 | call to singleton_m | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:74:1:74:1 | d | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:74:1:74:12 | call to instance_m | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:76:1:79:3 | optional_arg | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:76:18:76:18 | a | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:76:18:76:18 | a | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:76:22:76:22 | 4 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:76:25:76:25 | b | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:76:25:76:25 | b | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:76:28:76:28 | 5 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:77:5:77:5 | a | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:77:5:77:16 | call to bit_length | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:78:5:78:5 | b | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:78:5:78:16 | call to bit_length | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:81:1:83:3 | call_block | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:82:5:82:11 | yield ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:82:11:82:11 | 1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:85:1:89:3 | foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:86:5:86:7 | var | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:86:5:86:18 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:86:11:86:14 | Hash | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:86:11:86:18 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:87:5:87:7 | var | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:87:5:87:10 | ...[...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:87:9:87:9 | 1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:88:5:88:29 | call to call_block | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:88:5:88:29 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:88:16:88:29 | { ... } | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:88:19:88:19 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:88:19:88:19 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:88:22:88:24 | var | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:88:22:88:27 | ...[...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:88:26:88:26 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:91:1:94:3 | Integer | calls.rb:1:1:667:52 | calls.rb | | calls.rb:92:5:92:23 | bit_length | calls.rb:91:1:94:3 | Integer | | calls.rb:93:5:93:16 | abs | calls.rb:91:1:94:3 | Integer | -| calls.rb:96:1:98:3 | String | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:96:1:98:3 | String | calls.rb:1:1:667:52 | calls.rb | | calls.rb:97:5:97:23 | capitalize | calls.rb:96:1:98:3 | String | -| calls.rb:100:1:103:3 | Kernel | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:100:1:103:3 | Kernel | calls.rb:1:1:667:52 | calls.rb | | calls.rb:101:5:101:25 | alias ... | calls.rb:100:1:103:3 | Kernel | | calls.rb:101:11:101:19 | :old_puts | calls.rb:100:1:103:3 | Kernel | | calls.rb:101:11:101:19 | old_puts | calls.rb:100:1:103:3 | Kernel | @@ -701,7 +704,7 @@ enclosingModule | calls.rb:102:17:102:26 | call to old_puts | calls.rb:100:1:103:3 | Kernel | | calls.rb:102:17:102:26 | self | calls.rb:100:1:103:3 | Kernel | | calls.rb:102:26:102:26 | x | calls.rb:100:1:103:3 | Kernel | -| calls.rb:105:1:113:3 | Module | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:105:1:113:3 | Module | calls.rb:1:1:667:52 | calls.rb | | calls.rb:106:5:106:31 | alias ... | calls.rb:105:1:113:3 | Module | | calls.rb:106:11:106:22 | :old_include | calls.rb:105:1:113:3 | Module | | calls.rb:106:11:106:22 | old_include | calls.rb:105:1:113:3 | Module | @@ -716,13 +719,13 @@ enclosingModule | calls.rb:109:21:109:21 | x | calls.rb:105:1:113:3 | Module | | calls.rb:111:5:111:20 | prepend | calls.rb:105:1:113:3 | Module | | calls.rb:112:5:112:20 | private | calls.rb:105:1:113:3 | Module | -| calls.rb:115:1:118:3 | Object | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:115:16:115:21 | Module | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:115:1:118:3 | Object | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:115:16:115:21 | Module | calls.rb:1:1:667:52 | calls.rb | | calls.rb:116:5:116:18 | call to include | calls.rb:115:1:118:3 | Object | | calls.rb:116:5:116:18 | self | calls.rb:115:1:118:3 | Object | | calls.rb:116:13:116:18 | Kernel | calls.rb:115:1:118:3 | Object | | calls.rb:117:5:117:16 | new | calls.rb:115:1:118:3 | Object | -| calls.rb:120:1:123:3 | Hash | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:120:1:123:3 | Hash | calls.rb:1:1:667:52 | calls.rb | | calls.rb:121:5:121:25 | alias ... | calls.rb:120:1:123:3 | Hash | | calls.rb:121:11:121:21 | :old_lookup | calls.rb:120:1:123:3 | Hash | | calls.rb:121:11:121:21 | old_lookup | calls.rb:120:1:123:3 | Hash | @@ -734,7 +737,7 @@ enclosingModule | calls.rb:122:15:122:27 | call to old_lookup | calls.rb:120:1:123:3 | Hash | | calls.rb:122:15:122:27 | self | calls.rb:120:1:123:3 | Hash | | calls.rb:122:26:122:26 | x | calls.rb:120:1:123:3 | Hash | -| calls.rb:125:1:138:3 | Array | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:125:1:138:3 | Array | calls.rb:1:1:667:52 | calls.rb | | calls.rb:126:3:126:23 | alias ... | calls.rb:125:1:138:3 | Array | | calls.rb:126:9:126:19 | :old_lookup | calls.rb:125:1:138:3 | Array | | calls.rb:126:9:126:19 | old_lookup | calls.rb:125:1:138:3 | Array | @@ -770,130 +773,130 @@ enclosingModule | calls.rb:135:9:135:14 | ... = ... | calls.rb:125:1:138:3 | Array | | calls.rb:135:11:135:12 | ... + ... | calls.rb:125:1:138:3 | Array | | calls.rb:135:14:135:14 | 1 | calls.rb:125:1:138:3 | Array | -| calls.rb:140:1:142:3 | funny | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:141:5:141:20 | yield ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:141:11:141:20 | "prefix: " | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:141:12:141:19 | prefix: | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:144:1:144:30 | call to funny | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:144:1:144:30 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:144:7:144:30 | { ... } | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:144:10:144:10 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:144:10:144:10 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:144:13:144:29 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:144:13:144:29 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:144:18:144:18 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:144:18:144:29 | call to capitalize | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:146:1:146:3 | "a" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:146:1:146:14 | call to capitalize | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:146:2:146:2 | a | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:147:1:147:1 | 1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:147:1:147:12 | call to bit_length | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:148:1:148:1 | 1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:148:1:148:5 | call to abs | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:1:150:13 | Array | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:1:150:13 | [...] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:1:150:13 | call to [] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:1:150:62 | call to foreach | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:2:150:4 | "a" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:3:150:3 | a | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:6:150:8 | "b" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:7:150:7 | b | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:10:150:12 | "c" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:11:150:11 | c | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:23:150:62 | { ... } | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:26:150:26 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:26:150:26 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:29:150:29 | v | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:29:150:29 | v | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:32:150:61 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:32:150:61 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:37:150:61 | "#{...} -> #{...}" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:38:150:41 | #{...} | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:40:150:40 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:42:150:45 | -> | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:46:150:60 | #{...} | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:48:150:48 | v | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:150:48:150:59 | call to capitalize | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:1:152:7 | Array | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:1:152:7 | [...] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:1:152:7 | call to [] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:1:152:35 | call to foreach | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:2:152:2 | 1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:4:152:4 | 2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:6:152:6 | 3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:17:152:35 | { ... } | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:20:152:20 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:20:152:20 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:23:152:23 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:152:23:152:34 | call to bit_length | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:1:154:7 | Array | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:1:154:7 | [...] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:1:154:7 | call to [] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:1:154:40 | call to foreach | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:2:154:2 | 1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:4:154:4 | 2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:6:154:6 | 3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:17:154:40 | { ... } | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:20:154:20 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:20:154:20 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:23:154:39 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:23:154:39 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:28:154:28 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:154:28:154:39 | call to capitalize | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:1:156:8 | Array | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:1:156:8 | [...] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:1:156:8 | call to [] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:1:156:37 | call to foreach | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:2:156:2 | 1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:4:156:5 | - ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:5:156:5 | 2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:7:156:7 | 3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:18:156:37 | { ... } | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:21:156:21 | _ | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:21:156:21 | _ | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:24:156:24 | v | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:24:156:24 | v | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:27:156:36 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:27:156:36 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:32:156:32 | v | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:156:32:156:36 | call to abs | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:158:1:160:3 | indirect | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:158:14:158:15 | &b | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:158:15:158:15 | b | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:159:5:159:17 | call to call_block | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:159:5:159:17 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:159:16:159:17 | &... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:159:17:159:17 | b | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:162:1:162:28 | call to indirect | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:162:1:162:28 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:162:10:162:28 | { ... } | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:162:13:162:13 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:162:13:162:13 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:162:16:162:16 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:162:16:162:27 | call to bit_length | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:165:1:169:3 | S | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:140:1:142:3 | funny | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:141:5:141:20 | yield ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:141:11:141:20 | "prefix: " | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:141:12:141:19 | prefix: | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:144:1:144:30 | call to funny | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:144:1:144:30 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:144:7:144:30 | { ... } | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:144:10:144:10 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:144:10:144:10 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:144:13:144:29 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:144:13:144:29 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:144:18:144:18 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:144:18:144:29 | call to capitalize | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:146:1:146:3 | "a" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:146:1:146:14 | call to capitalize | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:146:2:146:2 | a | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:147:1:147:1 | 1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:147:1:147:12 | call to bit_length | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:148:1:148:1 | 1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:148:1:148:5 | call to abs | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:1:150:13 | Array | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:1:150:13 | [...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:1:150:13 | call to [] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:1:150:62 | call to foreach | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:2:150:4 | "a" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:3:150:3 | a | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:6:150:8 | "b" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:7:150:7 | b | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:10:150:12 | "c" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:11:150:11 | c | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:23:150:62 | { ... } | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:26:150:26 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:26:150:26 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:29:150:29 | v | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:29:150:29 | v | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:32:150:61 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:32:150:61 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:37:150:61 | "#{...} -> #{...}" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:38:150:41 | #{...} | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:40:150:40 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:42:150:45 | -> | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:46:150:60 | #{...} | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:48:150:48 | v | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:150:48:150:59 | call to capitalize | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:1:152:7 | Array | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:1:152:7 | [...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:1:152:7 | call to [] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:1:152:35 | call to foreach | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:2:152:2 | 1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:4:152:4 | 2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:6:152:6 | 3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:17:152:35 | { ... } | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:20:152:20 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:20:152:20 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:23:152:23 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:152:23:152:34 | call to bit_length | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:1:154:7 | Array | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:1:154:7 | [...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:1:154:7 | call to [] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:1:154:40 | call to foreach | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:2:154:2 | 1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:4:154:4 | 2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:6:154:6 | 3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:17:154:40 | { ... } | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:20:154:20 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:20:154:20 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:23:154:39 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:23:154:39 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:28:154:28 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:154:28:154:39 | call to capitalize | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:1:156:8 | Array | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:1:156:8 | [...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:1:156:8 | call to [] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:1:156:37 | call to foreach | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:2:156:2 | 1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:4:156:5 | - ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:5:156:5 | 2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:7:156:7 | 3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:18:156:37 | { ... } | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:21:156:21 | _ | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:21:156:21 | _ | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:24:156:24 | v | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:24:156:24 | v | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:27:156:36 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:27:156:36 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:32:156:32 | v | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:156:32:156:36 | call to abs | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:158:1:160:3 | indirect | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:158:14:158:15 | &b | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:158:15:158:15 | b | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:159:5:159:17 | call to call_block | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:159:5:159:17 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:159:16:159:17 | &... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:159:17:159:17 | b | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:162:1:162:28 | call to indirect | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:162:1:162:28 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:162:10:162:28 | { ... } | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:162:13:162:13 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:162:13:162:13 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:162:16:162:16 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:162:16:162:27 | call to bit_length | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:165:1:169:3 | S | calls.rb:1:1:667:52 | calls.rb | | calls.rb:166:5:168:7 | s_method | calls.rb:165:1:169:3 | S | | calls.rb:167:9:167:12 | self | calls.rb:165:1:169:3 | S | | calls.rb:167:9:167:17 | call to to_s | calls.rb:165:1:169:3 | S | -| calls.rb:171:1:174:3 | A | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:171:11:171:11 | S | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:171:1:174:3 | A | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:171:11:171:11 | S | calls.rb:1:1:667:52 | calls.rb | | calls.rb:172:5:173:7 | to_s | calls.rb:171:1:174:3 | A | -| calls.rb:176:1:179:3 | B | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:176:11:176:11 | S | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:176:1:179:3 | B | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:176:11:176:11 | S | calls.rb:1:1:667:52 | calls.rb | | calls.rb:177:5:178:7 | to_s | calls.rb:176:1:179:3 | B | -| calls.rb:181:1:181:1 | S | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:181:1:181:5 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:181:1:181:14 | call to s_method | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:182:1:182:1 | A | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:182:1:182:5 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:182:1:182:14 | call to s_method | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:183:1:183:1 | B | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:183:1:183:5 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:183:1:183:14 | call to s_method | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:185:1:186:3 | private_on_main | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:188:1:188:15 | call to private_on_main | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:188:1:188:15 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:190:1:226:3 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:181:1:181:1 | S | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:181:1:181:5 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:181:1:181:14 | call to s_method | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:182:1:182:1 | A | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:182:1:182:5 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:182:1:182:14 | call to s_method | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:183:1:183:1 | B | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:183:1:183:5 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:183:1:183:14 | call to s_method | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:185:1:186:3 | private_on_main | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:188:1:188:15 | call to private_on_main | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:188:1:188:15 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:190:1:226:3 | Singletons | calls.rb:1:1:667:52 | calls.rb | | calls.rb:191:5:194:7 | singleton_a | calls.rb:190:1:226:3 | Singletons | | calls.rb:191:9:191:12 | self | calls.rb:190:1:226:3 | Singletons | | calls.rb:192:9:192:26 | call to puts | calls.rb:190:1:226:3 | Singletons | @@ -943,126 +946,126 @@ enclosingModule | calls.rb:223:5:225:7 | call_singleton_g | calls.rb:190:1:226:3 | Singletons | | calls.rb:224:9:224:12 | self | calls.rb:190:1:226:3 | Singletons | | calls.rb:224:9:224:24 | call to singleton_g | calls.rb:190:1:226:3 | Singletons | -| calls.rb:228:1:228:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:228:1:228:22 | call to singleton_a | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:229:1:229:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:229:1:229:22 | call to singleton_f | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:231:1:231:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:231:1:231:19 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:231:6:231:15 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:231:6:231:19 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:233:1:233:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:233:1:233:11 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:234:1:234:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:234:1:234:14 | call to singleton_e | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:236:1:238:3 | singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:236:5:236:6 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:237:5:237:24 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:237:5:237:24 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:237:10:237:24 | "singleton_g_1" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:237:11:237:23 | singleton_g_1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:240:1:240:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:240:1:240:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:241:1:241:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:241:1:241:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:243:1:245:3 | singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:243:5:243:6 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:244:5:244:24 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:244:5:244:24 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:244:10:244:24 | "singleton_g_2" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:244:11:244:23 | singleton_g_2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:247:1:247:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:247:1:247:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:248:1:248:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:248:1:248:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:250:1:254:3 | class << ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:250:10:250:11 | c1 | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:228:1:228:10 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:228:1:228:22 | call to singleton_a | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:229:1:229:10 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:229:1:229:22 | call to singleton_f | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:231:1:231:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:231:1:231:19 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:231:6:231:15 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:231:6:231:19 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:233:1:233:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:233:1:233:11 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:234:1:234:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:234:1:234:14 | call to singleton_e | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:236:1:238:3 | singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:236:5:236:6 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:237:5:237:24 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:237:5:237:24 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:237:10:237:24 | "singleton_g_1" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:237:11:237:23 | singleton_g_1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:240:1:240:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:240:1:240:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:241:1:241:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:241:1:241:19 | call to call_singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:243:1:245:3 | singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:243:5:243:6 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:244:5:244:24 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:244:5:244:24 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:244:10:244:24 | "singleton_g_2" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:244:11:244:23 | singleton_g_2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:247:1:247:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:247:1:247:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:248:1:248:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:248:1:248:19 | call to call_singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:250:1:254:3 | class << ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:250:10:250:11 | c1 | calls.rb:1:1:667:52 | calls.rb | | calls.rb:251:5:253:7 | singleton_g | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:9:252:28 | call to puts | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:9:252:28 | self | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:14:252:28 | "singleton_g_3" | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:15:252:27 | singleton_g_3 | calls.rb:250:1:254:3 | class << ... | -| calls.rb:256:1:256:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:256:1:256:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:257:1:257:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:257:1:257:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:259:1:259:2 | c2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:259:1:259:19 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:259:6:259:15 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:259:6:259:19 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:260:1:260:2 | c2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:260:1:260:14 | call to singleton_e | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:261:1:261:2 | c2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:261:1:261:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:263:1:263:4 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:263:1:263:8 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:265:1:265:16 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:265:1:265:16 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:265:6:265:16 | "top-level" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:265:7:265:15 | top-level | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:267:1:269:3 | singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:267:5:267:14 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:268:5:268:22 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:268:5:268:22 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:268:10:268:22 | "singleton_g" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:268:11:268:21 | singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:271:1:271:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:271:1:271:22 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:272:1:272:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:272:1:272:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:273:1:273:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:273:1:273:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:274:1:274:2 | c2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:274:1:274:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:275:1:275:2 | c3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:275:1:275:19 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:275:6:275:15 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:275:6:275:19 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:276:1:276:2 | c3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:276:1:276:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:278:1:286:3 | create | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:278:12:278:15 | type | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:278:12:278:15 | type | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:279:5:279:8 | type | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:279:5:279:12 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:279:5:279:21 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:281:5:283:7 | singleton_h | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:281:9:281:12 | type | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:282:9:282:26 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:282:9:282:26 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:282:14:282:26 | "singleton_h" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:282:15:282:25 | singleton_h | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:285:5:285:8 | type | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:285:5:285:20 | call to singleton_h | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:288:1:288:17 | call to create | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:288:1:288:17 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:288:8:288:17 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:289:1:289:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:289:1:289:22 | call to singleton_h | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:291:1:291:1 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:291:1:291:14 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:291:5:291:14 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:293:1:297:3 | class << ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:293:10:293:10 | x | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:256:1:256:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:256:1:256:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:257:1:257:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:257:1:257:19 | call to call_singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:259:1:259:2 | c2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:259:1:259:19 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:259:6:259:15 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:259:6:259:19 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:260:1:260:2 | c2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:260:1:260:14 | call to singleton_e | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:261:1:261:2 | c2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:261:1:261:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:263:1:263:4 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:263:1:263:8 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:265:1:265:16 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:265:1:265:16 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:265:6:265:16 | "top-level" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:265:7:265:15 | top-level | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:267:1:269:3 | singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:267:5:267:14 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:268:5:268:22 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:268:5:268:22 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:268:10:268:22 | "singleton_g" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:268:11:268:21 | singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:271:1:271:10 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:271:1:271:22 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:272:1:272:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:272:1:272:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:273:1:273:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:273:1:273:19 | call to call_singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:274:1:274:2 | c2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:274:1:274:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:275:1:275:2 | c3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:275:1:275:19 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:275:6:275:15 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:275:6:275:19 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:276:1:276:2 | c3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:276:1:276:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:278:1:286:3 | create | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:278:12:278:15 | type | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:278:12:278:15 | type | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:279:5:279:8 | type | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:279:5:279:12 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:279:5:279:21 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:281:5:283:7 | singleton_h | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:281:9:281:12 | type | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:282:9:282:26 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:282:9:282:26 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:282:14:282:26 | "singleton_h" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:282:15:282:25 | singleton_h | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:285:5:285:8 | type | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:285:5:285:20 | call to singleton_h | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:288:1:288:17 | call to create | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:288:1:288:17 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:288:8:288:17 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:289:1:289:10 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:289:1:289:22 | call to singleton_h | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:291:1:291:1 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:291:1:291:14 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:291:5:291:14 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:293:1:297:3 | class << ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:293:10:293:10 | x | calls.rb:1:1:667:52 | calls.rb | | calls.rb:294:5:296:7 | singleton_i | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:9:295:26 | call to puts | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:9:295:26 | self | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:14:295:26 | "singleton_i" | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:15:295:25 | singleton_i | calls.rb:293:1:297:3 | class << ... | -| calls.rb:299:1:299:1 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:299:1:299:13 | call to singleton_i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:300:1:300:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:300:1:300:22 | call to singleton_i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:302:1:306:3 | class << ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:302:10:302:19 | Singletons | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:299:1:299:1 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:299:1:299:13 | call to singleton_i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:300:1:300:10 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:300:1:300:22 | call to singleton_i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:302:1:306:3 | class << ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:302:10:302:19 | Singletons | calls.rb:1:1:667:52 | calls.rb | | calls.rb:303:5:305:7 | singleton_j | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:9:304:26 | call to puts | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:9:304:26 | self | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:14:304:26 | "singleton_j" | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:15:304:25 | singleton_j | calls.rb:302:1:306:3 | class << ... | -| calls.rb:308:1:308:10 | Singletons | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:308:1:308:22 | call to singleton_j | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:310:1:321:3 | SelfNew | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:308:1:308:10 | Singletons | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:308:1:308:22 | call to singleton_j | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:310:1:321:3 | SelfNew | calls.rb:1:1:667:52 | calls.rb | | calls.rb:311:5:314:7 | instance | calls.rb:310:1:321:3 | SelfNew | | calls.rb:312:9:312:31 | call to puts | calls.rb:310:1:321:3 | SelfNew | | calls.rb:312:9:312:31 | self | calls.rb:310:1:321:3 | SelfNew | @@ -1079,508 +1082,535 @@ enclosingModule | calls.rb:320:5:320:7 | call to new | calls.rb:310:1:321:3 | SelfNew | | calls.rb:320:5:320:7 | self | calls.rb:310:1:321:3 | SelfNew | | calls.rb:320:5:320:16 | call to instance | calls.rb:310:1:321:3 | SelfNew | -| calls.rb:323:1:323:7 | SelfNew | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:323:1:323:17 | call to singleton | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:325:1:329:3 | C1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:326:5:328:7 | instance | calls.rb:325:1:329:3 | C1 | -| calls.rb:327:9:327:26 | call to puts | calls.rb:325:1:329:3 | C1 | -| calls.rb:327:9:327:26 | self | calls.rb:325:1:329:3 | C1 | -| calls.rb:327:14:327:26 | "C1#instance" | calls.rb:325:1:329:3 | C1 | -| calls.rb:327:15:327:25 | C1#instance | calls.rb:325:1:329:3 | C1 | -| calls.rb:331:1:335:3 | C2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:331:12:331:13 | C1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:332:5:334:7 | instance | calls.rb:331:1:335:3 | C2 | -| calls.rb:333:9:333:26 | call to puts | calls.rb:331:1:335:3 | C2 | -| calls.rb:333:9:333:26 | self | calls.rb:331:1:335:3 | C2 | -| calls.rb:333:14:333:26 | "C2#instance" | calls.rb:331:1:335:3 | C2 | -| calls.rb:333:15:333:25 | C2#instance | calls.rb:331:1:335:3 | C2 | -| calls.rb:337:1:341:3 | C3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:337:12:337:13 | C2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:338:5:340:7 | instance | calls.rb:337:1:341:3 | C3 | -| calls.rb:339:9:339:26 | call to puts | calls.rb:337:1:341:3 | C3 | -| calls.rb:339:9:339:26 | self | calls.rb:337:1:341:3 | C3 | -| calls.rb:339:14:339:26 | "C3#instance" | calls.rb:337:1:341:3 | C3 | -| calls.rb:339:15:339:25 | C3#instance | calls.rb:337:1:341:3 | C3 | -| calls.rb:343:1:359:3 | pattern_dispatch | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:343:22:343:22 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:343:22:343:22 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:344:5:352:7 | case ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:344:10:344:10 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:345:5:346:18 | when ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:345:10:345:11 | C3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:345:12:346:18 | then ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:346:9:346:9 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:346:9:346:18 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:347:5:348:18 | when ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:347:10:347:11 | C2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:347:12:348:18 | then ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:348:9:348:9 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:348:9:348:18 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:349:5:350:18 | when ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:349:10:349:11 | C1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:349:12:350:18 | then ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:350:9:350:9 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:350:9:350:18 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:351:5:351:8 | else ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:354:5:358:7 | case ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:354:10:354:10 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:355:9:355:29 | in ... then ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:355:12:355:13 | C3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:355:15:355:29 | then ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:355:20:355:20 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:355:20:355:29 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:356:9:356:36 | in ... then ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:356:12:356:13 | C2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:356:12:356:19 | ... => ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:356:18:356:19 | c2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:356:21:356:36 | then ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:356:26:356:27 | c2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:356:26:356:36 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:357:9:357:36 | in ... then ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:357:12:357:13 | C1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:357:12:357:19 | ... => ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:357:18:357:19 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:357:21:357:36 | then ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:357:26:357:27 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:357:26:357:36 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:361:1:361:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:361:1:361:11 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:361:6:361:7 | C1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:361:6:361:11 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:362:1:362:2 | c1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:362:1:362:11 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:363:1:363:25 | call to pattern_dispatch | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:363:1:363:25 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:363:18:363:25 | ( ... ) | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:363:19:363:20 | C1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:363:19:363:24 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:364:1:364:25 | call to pattern_dispatch | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:364:1:364:25 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:364:18:364:25 | ( ... ) | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:364:19:364:20 | C2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:364:19:364:24 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:365:1:365:25 | call to pattern_dispatch | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:365:1:365:25 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:365:18:365:25 | ( ... ) | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:365:19:365:20 | C3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:365:19:365:24 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:367:1:371:3 | add_singleton | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:367:19:367:19 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:367:19:367:19 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:368:5:370:7 | instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:368:9:368:9 | x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:369:9:369:28 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:369:9:369:28 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:369:14:369:28 | "instance_on x" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:369:15:369:27 | instance_on x | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:373:1:373:2 | c3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:373:1:373:11 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:373:6:373:7 | C1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:373:6:373:11 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:374:1:374:16 | call to add_singleton | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:374:1:374:16 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:374:15:374:16 | c3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:375:1:375:2 | c3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:375:1:375:11 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:377:1:405:3 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:378:5:390:7 | class << ... | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:378:14:378:17 | self | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:379:9:381:11 | singleton1 | calls.rb:378:5:390:7 | class << ... | -| calls.rb:380:13:380:48 | call to puts | calls.rb:378:5:390:7 | class << ... | -| calls.rb:380:13:380:48 | self | calls.rb:378:5:390:7 | class << ... | -| calls.rb:380:18:380:48 | "SingletonOverride1#singleton1" | calls.rb:378:5:390:7 | class << ... | -| calls.rb:380:19:380:47 | SingletonOverride1#singleton1 | calls.rb:378:5:390:7 | class << ... | -| calls.rb:383:9:385:11 | call_singleton1 | calls.rb:378:5:390:7 | class << ... | -| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:378:5:390:7 | class << ... | -| calls.rb:384:13:384:22 | self | calls.rb:378:5:390:7 | class << ... | -| calls.rb:387:9:389:11 | factory | calls.rb:378:5:390:7 | class << ... | -| calls.rb:388:13:388:16 | self | calls.rb:378:5:390:7 | class << ... | -| calls.rb:388:13:388:20 | call to new | calls.rb:378:5:390:7 | class << ... | -| calls.rb:388:13:388:30 | call to instance1 | calls.rb:378:5:390:7 | class << ... | -| calls.rb:392:5:394:7 | singleton2 | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:392:9:392:12 | self | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:393:9:393:44 | call to puts | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:393:9:393:44 | self | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:393:14:393:44 | "SingletonOverride1#singleton2" | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:393:15:393:43 | SingletonOverride1#singleton2 | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:396:5:398:7 | call_singleton2 | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:396:9:396:12 | self | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:397:9:397:18 | call to singleton2 | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:397:9:397:18 | self | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:400:5:400:14 | call to singleton2 | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:400:5:400:14 | self | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:402:5:404:7 | instance1 | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:403:9:403:43 | call to puts | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:403:9:403:43 | self | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:403:14:403:43 | "SingletonOverride1#instance1" | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:403:15:403:42 | SingletonOverride1#instance1 | calls.rb:377:1:405:3 | SingletonOverride1 | -| calls.rb:407:1:407:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:407:1:407:29 | call to singleton1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:408:1:408:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:408:1:408:29 | call to singleton2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:409:1:409:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:409:1:409:34 | call to call_singleton1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:410:1:410:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:410:1:410:34 | call to call_singleton2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:412:1:426:3 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:412:28:412:45 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:413:5:417:7 | class << ... | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:413:14:413:17 | self | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:414:9:416:11 | singleton1 | calls.rb:413:5:417:7 | class << ... | -| calls.rb:415:13:415:48 | call to puts | calls.rb:413:5:417:7 | class << ... | -| calls.rb:415:13:415:48 | self | calls.rb:413:5:417:7 | class << ... | -| calls.rb:415:18:415:48 | "SingletonOverride2#singleton1" | calls.rb:413:5:417:7 | class << ... | -| calls.rb:415:19:415:47 | SingletonOverride2#singleton1 | calls.rb:413:5:417:7 | class << ... | -| calls.rb:419:5:421:7 | singleton2 | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:419:9:419:12 | self | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:420:9:420:44 | call to puts | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:420:9:420:44 | self | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:420:14:420:44 | "SingletonOverride2#singleton2" | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:420:15:420:43 | SingletonOverride2#singleton2 | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:423:5:425:7 | instance1 | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:424:9:424:43 | call to puts | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:424:9:424:43 | self | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:424:14:424:43 | "SingletonOverride2#instance1" | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:424:15:424:42 | SingletonOverride2#instance1 | calls.rb:412:1:426:3 | SingletonOverride2 | -| calls.rb:428:1:428:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:428:1:428:29 | call to singleton1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:429:1:429:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:429:1:429:29 | call to singleton2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:430:1:430:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:430:1:430:34 | call to call_singleton1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:431:1:431:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:431:1:431:34 | call to call_singleton2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:433:1:461:3 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:434:5:438:7 | if ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:434:8:434:13 | call to rand | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:434:8:434:13 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:434:8:434:17 | ... > ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:434:17:434:17 | 0 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:434:19:437:11 | then ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:435:9:437:11 | m1 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:436:13:436:48 | call to puts | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:436:13:436:48 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:436:18:436:48 | "ConditionalInstanceMethods#m1" | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:436:19:436:47 | ConditionalInstanceMethods#m1 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:440:5:452:7 | m2 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:441:9:441:44 | call to puts | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:441:9:441:44 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:441:14:441:44 | "ConditionalInstanceMethods#m2" | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:441:15:441:43 | ConditionalInstanceMethods#m2 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:443:9:449:11 | m3 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:444:13:444:48 | call to puts | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:444:13:444:48 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:444:18:444:48 | "ConditionalInstanceMethods#m3" | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:444:19:444:47 | ConditionalInstanceMethods#m3 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:446:13:448:15 | m4 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:447:17:447:52 | call to puts | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:447:17:447:52 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:447:22:447:52 | "ConditionalInstanceMethods#m4" | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:447:23:447:51 | ConditionalInstanceMethods#m4 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:451:9:451:10 | call to m3 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:451:9:451:10 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:454:5:460:7 | if ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:454:8:454:13 | call to rand | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:454:8:454:13 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:454:8:454:17 | ... > ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:454:17:454:17 | 0 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:454:19:459:18 | then ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:455:9:455:13 | Class | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:455:9:459:11 | call to new | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:455:9:459:15 | call to new | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:455:9:459:18 | call to m5 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:455:19:459:11 | do ... end | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:456:13:458:15 | m5 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:457:17:457:40 | call to puts | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:457:17:457:40 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:457:22:457:40 | "AnonymousClass#m5" | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:457:23:457:39 | AnonymousClass#m5 | calls.rb:433:1:461:3 | ConditionalInstanceMethods | -| calls.rb:463:1:463:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:463:1:463:30 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:463:1:463:33 | call to m1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:464:1:464:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:464:1:464:30 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:464:1:464:33 | call to m3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:465:1:465:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:465:1:465:30 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:465:1:465:33 | call to m2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:466:1:466:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:466:1:466:30 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:466:1:466:33 | call to m3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:467:1:467:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:467:1:467:30 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:467:1:467:33 | call to m4 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:468:1:468:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:468:1:468:30 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:468:1:468:33 | call to m5 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:470:1:470:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:470:1:488:3 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:470:27:470:31 | Class | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:470:27:488:3 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:470:37:488:3 | do ... end | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:471:5:471:11 | Array | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:471:5:471:11 | [...] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:471:5:471:11 | call to [] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:471:5:475:7 | call to each | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:471:6:471:6 | 0 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:471:8:471:8 | 1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:471:10:471:10 | 2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:471:18:475:7 | do ... end | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:472:9:474:11 | foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:473:13:473:22 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:473:13:473:22 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:473:18:473:22 | "foo" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:473:19:473:21 | foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:477:5:477:9 | Class | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:477:5:481:7 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:477:5:481:11 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:477:5:481:15 | call to bar | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:477:15:481:7 | do ... end | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:478:9:480:11 | bar | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:479:13:479:22 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:479:13:479:22 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:479:18:479:22 | "bar" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:479:19:479:21 | bar | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:483:5:483:11 | Array | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:483:5:483:11 | [...] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:483:5:483:11 | call to [] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:483:5:487:7 | call to each | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:483:6:483:6 | 0 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:483:8:483:8 | 1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:483:10:483:10 | 2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:483:18:487:7 | do ... end | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:483:22:483:22 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:483:22:483:22 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:484:9:486:11 | call to define_method | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:484:9:486:11 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:484:23:484:32 | "baz_#{...}" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:484:24:484:27 | baz_ | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:484:28:484:31 | #{...} | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:484:30:484:30 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:484:35:486:11 | do ... end | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:485:13:485:27 | call to puts | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:485:13:485:27 | self | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:485:18:485:27 | "baz_#{...}" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:485:19:485:22 | baz_ | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:485:23:485:26 | #{...} | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:485:25:485:25 | i | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:490:1:490:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:490:1:490:27 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:490:1:490:31 | call to foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:491:1:491:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:491:1:491:27 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:491:1:491:31 | call to bar | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:492:1:492:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:492:1:492:27 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:492:1:492:33 | call to baz_0 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:493:1:493:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:493:1:493:27 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:493:1:493:33 | call to baz_1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:494:1:494:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:494:1:494:27 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:494:1:494:33 | call to baz_2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:496:1:502:3 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:497:5:499:7 | singleton | calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:498:9:498:46 | call to puts | calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:498:9:498:46 | self | calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:498:14:498:46 | "ExtendSingletonMethod#singleton" | calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:498:15:498:45 | ExtendSingletonMethod#singleton | calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:501:5:501:15 | call to extend | calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:501:5:501:15 | self | calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:501:12:501:15 | self | calls.rb:496:1:502:3 | ExtendSingletonMethod | -| calls.rb:504:1:504:21 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:504:1:504:31 | call to singleton | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:506:1:508:3 | ExtendSingletonMethod2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:507:5:507:32 | call to extend | calls.rb:506:1:508:3 | ExtendSingletonMethod2 | -| calls.rb:507:5:507:32 | self | calls.rb:506:1:508:3 | ExtendSingletonMethod2 | -| calls.rb:507:12:507:32 | ExtendSingletonMethod | calls.rb:506:1:508:3 | ExtendSingletonMethod2 | -| calls.rb:510:1:510:22 | ExtendSingletonMethod2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:510:1:510:32 | call to singleton | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:512:1:513:3 | ExtendSingletonMethod3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:515:1:515:22 | ExtendSingletonMethod3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:515:1:515:51 | call to extend | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:515:31:515:51 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:517:1:517:22 | ExtendSingletonMethod3 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:517:1:517:32 | call to singleton | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:519:1:519:3 | foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:519:1:519:13 | ... = ... | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:519:7:519:13 | "hello" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:519:8:519:12 | hello | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:520:1:520:3 | foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:520:1:520:13 | call to singleton | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:521:1:521:3 | foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:521:1:521:32 | call to extend | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:521:12:521:32 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:523:1:523:3 | foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:523:1:523:13 | call to singleton | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:525:1:529:3 | ProtectedMethodInModule | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:526:5:528:7 | call to protected | calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:526:5:528:7 | self | calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:526:15:528:7 | foo | calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:527:9:527:42 | call to puts | calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:527:9:527:42 | self | calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:527:14:527:42 | "ProtectedMethodInModule#foo" | calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:527:15:527:41 | ProtectedMethodInModule#foo | calls.rb:525:1:529:3 | ProtectedMethodInModule | -| calls.rb:531:1:544:3 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:532:5:532:35 | call to include | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:532:5:532:35 | self | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:532:13:532:35 | ProtectedMethodInModule | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:534:5:536:7 | call to protected | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:534:5:536:7 | self | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:534:15:536:7 | bar | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:535:9:535:35 | call to puts | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:535:9:535:35 | self | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:535:14:535:35 | "ProtectedMethods#bar" | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:535:15:535:34 | ProtectedMethods#bar | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:538:5:543:7 | baz | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:539:9:539:11 | call to foo | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:539:9:539:11 | self | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:540:9:540:11 | call to bar | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:540:9:540:11 | self | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:541:9:541:24 | ProtectedMethods | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:541:9:541:28 | call to new | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:541:9:541:32 | call to foo | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:542:9:542:24 | ProtectedMethods | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:542:9:542:28 | call to new | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:542:9:542:32 | call to bar | calls.rb:531:1:544:3 | ProtectedMethods | -| calls.rb:546:1:546:16 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:546:1:546:20 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:546:1:546:24 | call to foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:547:1:547:16 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:547:1:547:20 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:547:1:547:24 | call to bar | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:548:1:548:16 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:548:1:548:20 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:548:1:548:24 | call to baz | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:550:1:555:3 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:550:29:550:44 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:551:5:554:7 | baz | calls.rb:550:1:555:3 | ProtectedMethodsSub | -| calls.rb:552:9:552:11 | call to foo | calls.rb:550:1:555:3 | ProtectedMethodsSub | -| calls.rb:552:9:552:11 | self | calls.rb:550:1:555:3 | ProtectedMethodsSub | -| calls.rb:553:9:553:27 | ProtectedMethodsSub | calls.rb:550:1:555:3 | ProtectedMethodsSub | -| calls.rb:553:9:553:31 | call to new | calls.rb:550:1:555:3 | ProtectedMethodsSub | -| calls.rb:553:9:553:35 | call to foo | calls.rb:550:1:555:3 | ProtectedMethodsSub | -| calls.rb:557:1:557:19 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:557:1:557:23 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:557:1:557:27 | call to foo | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:558:1:558:19 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:558:1:558:23 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:558:1:558:27 | call to bar | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:559:1:559:19 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:559:1:559:23 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:559:1:559:27 | call to baz | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:1:561:7 | Array | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:1:561:7 | [...] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:1:561:7 | call to [] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:1:561:26 | call to each | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:2:561:2 | C | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:2:561:6 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:14:561:26 | { ... } | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:17:561:17 | c | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:17:561:17 | c | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:20:561:20 | c | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:561:20:561:24 | call to baz | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:1:562:13 | Array | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:1:562:13 | [...] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:1:562:13 | call to [] | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:1:562:39 | call to each | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:2:562:4 | "a" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:3:562:3 | a | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:6:562:8 | "b" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:7:562:7 | b | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:10:562:12 | "c" | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:11:562:11 | c | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:20:562:39 | { ... } | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:23:562:23 | s | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:23:562:23 | s | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:26:562:26 | s | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:562:26:562:37 | call to capitalize | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:564:1:567:3 | SingletonUpCall_Base | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:565:5:566:7 | singleton | calls.rb:564:1:567:3 | SingletonUpCall_Base | -| calls.rb:565:9:565:12 | self | calls.rb:564:1:567:3 | SingletonUpCall_Base | -| calls.rb:568:1:575:3 | SingletonUpCall_Sub | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:568:29:568:48 | SingletonUpCall_Base | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:569:5:569:13 | call to singleton | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:569:5:569:13 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:570:5:570:14 | call to singleton2 | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:570:5:570:14 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:571:5:574:7 | mid_method | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:571:9:571:12 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:572:9:572:17 | call to singleton | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:572:9:572:17 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:573:9:573:18 | call to singleton2 | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:573:9:573:18 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub | -| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:576:32:576:50 | SingletonUpCall_Sub | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:577:5:578:7 | singleton2 | calls.rb:576:1:581:3 | SingletonUpCall_SubSub | -| calls.rb:577:9:577:12 | self | calls.rb:576:1:581:3 | SingletonUpCall_SubSub | -| calls.rb:580:5:580:14 | call to mid_method | calls.rb:576:1:581:3 | SingletonUpCall_SubSub | -| calls.rb:580:5:580:14 | self | calls.rb:576:1:581:3 | SingletonUpCall_SubSub | -| calls.rb:583:1:594:3 | SingletonA | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:584:5:585:7 | singleton1 | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:584:9:584:12 | self | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:587:5:589:7 | call_singleton1 | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:587:9:587:12 | self | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:588:9:588:18 | self | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:591:5:593:7 | call_call_singleton1 | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:591:9:591:12 | self | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:592:9:592:23 | self | calls.rb:583:1:594:3 | SingletonA | -| calls.rb:596:1:603:3 | SingletonB | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:596:20:596:29 | SingletonA | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:597:5:598:7 | singleton1 | calls.rb:596:1:603:3 | SingletonB | -| calls.rb:597:9:597:12 | self | calls.rb:596:1:603:3 | SingletonB | -| calls.rb:600:5:602:7 | call_singleton1 | calls.rb:596:1:603:3 | SingletonB | -| calls.rb:600:9:600:12 | self | calls.rb:596:1:603:3 | SingletonB | -| calls.rb:601:9:601:18 | call to singleton1 | calls.rb:596:1:603:3 | SingletonB | -| calls.rb:601:9:601:18 | self | calls.rb:596:1:603:3 | SingletonB | -| calls.rb:605:1:612:3 | SingletonC | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:605:20:605:29 | SingletonA | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:606:5:607:7 | singleton1 | calls.rb:605:1:612:3 | SingletonC | -| calls.rb:606:9:606:12 | self | calls.rb:605:1:612:3 | SingletonC | -| calls.rb:609:5:611:7 | call_singleton1 | calls.rb:605:1:612:3 | SingletonC | -| calls.rb:609:9:609:12 | self | calls.rb:605:1:612:3 | SingletonC | -| calls.rb:610:9:610:18 | call to singleton1 | calls.rb:605:1:612:3 | SingletonC | -| calls.rb:610:9:610:18 | self | calls.rb:605:1:612:3 | SingletonC | -| calls.rb:614:1:614:10 | SingletonA | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:614:1:614:31 | call to call_call_singleton1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:615:1:615:10 | SingletonB | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:615:1:615:31 | call to call_call_singleton1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:616:1:616:10 | SingletonC | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:616:1:616:31 | call to call_call_singleton1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:618:1:624:3 | Included | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:619:5:621:7 | foo | calls.rb:618:1:624:3 | Included | -| calls.rb:620:9:620:12 | self | calls.rb:618:1:624:3 | Included | -| calls.rb:620:9:620:16 | call to bar | calls.rb:618:1:624:3 | Included | -| calls.rb:622:5:623:7 | bar | calls.rb:618:1:624:3 | Included | -| calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:627:5:627:20 | call to include | calls.rb:626:1:631:3 | IncludesIncluded | -| calls.rb:627:5:627:20 | self | calls.rb:626:1:631:3 | IncludesIncluded | -| calls.rb:627:13:627:20 | Included | calls.rb:626:1:631:3 | IncludesIncluded | -| calls.rb:628:5:630:7 | bar | calls.rb:626:1:631:3 | IncludesIncluded | -| calls.rb:629:9:629:13 | super call to bar | calls.rb:626:1:631:3 | IncludesIncluded | -| calls.rb:633:1:637:3 | CustomNew1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:634:5:636:7 | new | calls.rb:633:1:637:3 | CustomNew1 | -| calls.rb:634:9:634:12 | self | calls.rb:633:1:637:3 | CustomNew1 | -| calls.rb:635:9:635:10 | C1 | calls.rb:633:1:637:3 | CustomNew1 | -| calls.rb:635:9:635:14 | call to new | calls.rb:633:1:637:3 | CustomNew1 | -| calls.rb:639:1:639:10 | CustomNew1 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:639:1:639:14 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:639:1:639:23 | call to instance | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:641:1:649:3 | CustomNew2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:642:5:644:7 | new | calls.rb:641:1:649:3 | CustomNew2 | -| calls.rb:642:9:642:12 | self | calls.rb:641:1:649:3 | CustomNew2 | -| calls.rb:643:9:643:12 | self | calls.rb:641:1:649:3 | CustomNew2 | -| calls.rb:643:9:643:21 | call to allocate | calls.rb:641:1:649:3 | CustomNew2 | -| calls.rb:646:5:648:7 | instance | calls.rb:641:1:649:3 | CustomNew2 | -| calls.rb:647:9:647:34 | call to puts | calls.rb:641:1:649:3 | CustomNew2 | -| calls.rb:647:9:647:34 | self | calls.rb:641:1:649:3 | CustomNew2 | -| calls.rb:647:14:647:34 | "CustomNew2#instance" | calls.rb:641:1:649:3 | CustomNew2 | -| calls.rb:647:15:647:33 | CustomNew2#instance | calls.rb:641:1:649:3 | CustomNew2 | -| calls.rb:651:1:651:10 | CustomNew2 | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:651:1:651:14 | call to new | calls.rb:1:1:651:24 | calls.rb | -| calls.rb:651:1:651:23 | call to instance | calls.rb:1:1:651:24 | calls.rb | +| calls.rb:323:1:323:7 | SelfNew | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:323:1:323:17 | call to singleton | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:325:1:333:3 | C1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:326:5:328:7 | instance | calls.rb:325:1:333:3 | C1 | +| calls.rb:327:9:327:26 | call to puts | calls.rb:325:1:333:3 | C1 | +| calls.rb:327:9:327:26 | self | calls.rb:325:1:333:3 | C1 | +| calls.rb:327:14:327:26 | "C1#instance" | calls.rb:325:1:333:3 | C1 | +| calls.rb:327:15:327:25 | C1#instance | calls.rb:325:1:333:3 | C1 | +| calls.rb:330:5:332:7 | return_self | calls.rb:325:1:333:3 | C1 | +| calls.rb:331:9:331:12 | self | calls.rb:325:1:333:3 | C1 | +| calls.rb:335:1:339:3 | C2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:335:12:335:13 | C1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:336:5:338:7 | instance | calls.rb:335:1:339:3 | C2 | +| calls.rb:337:9:337:26 | call to puts | calls.rb:335:1:339:3 | C2 | +| calls.rb:337:9:337:26 | self | calls.rb:335:1:339:3 | C2 | +| calls.rb:337:14:337:26 | "C2#instance" | calls.rb:335:1:339:3 | C2 | +| calls.rb:337:15:337:25 | C2#instance | calls.rb:335:1:339:3 | C2 | +| calls.rb:341:1:345:3 | C3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:341:12:341:13 | C2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:342:5:344:7 | instance | calls.rb:341:1:345:3 | C3 | +| calls.rb:343:9:343:26 | call to puts | calls.rb:341:1:345:3 | C3 | +| calls.rb:343:9:343:26 | self | calls.rb:341:1:345:3 | C3 | +| calls.rb:343:14:343:26 | "C3#instance" | calls.rb:341:1:345:3 | C3 | +| calls.rb:343:15:343:25 | C3#instance | calls.rb:341:1:345:3 | C3 | +| calls.rb:347:1:363:3 | pattern_dispatch | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:347:22:347:22 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:347:22:347:22 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:348:5:356:7 | case ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:348:10:348:10 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:349:5:350:18 | when ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:349:10:349:11 | C3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:349:12:350:18 | then ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:350:9:350:9 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:350:9:350:18 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:351:5:352:18 | when ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:351:10:351:11 | C2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:351:12:352:18 | then ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:352:9:352:9 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:352:9:352:18 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:353:5:354:18 | when ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:353:10:353:11 | C1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:353:12:354:18 | then ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:354:9:354:9 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:354:9:354:18 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:355:5:355:8 | else ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:358:5:362:7 | case ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:358:10:358:10 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:359:9:359:29 | in ... then ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:359:12:359:13 | C3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:359:15:359:29 | then ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:359:20:359:20 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:359:20:359:29 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:360:9:360:36 | in ... then ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:360:12:360:13 | C2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:360:12:360:19 | ... => ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:360:18:360:19 | c2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:360:21:360:36 | then ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:360:26:360:27 | c2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:360:26:360:36 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:361:9:361:36 | in ... then ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:361:12:361:13 | C1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:361:12:361:19 | ... => ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:361:18:361:19 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:361:21:361:36 | then ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:361:26:361:27 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:361:26:361:36 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:365:1:365:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:365:1:365:11 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:365:6:365:7 | C1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:365:6:365:11 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:366:1:366:2 | c1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:366:1:366:11 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:368:1:368:25 | call to pattern_dispatch | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:368:1:368:25 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:368:18:368:25 | ( ... ) | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:368:19:368:20 | C1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:368:19:368:24 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:369:1:369:25 | call to pattern_dispatch | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:369:1:369:25 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:369:18:369:25 | ( ... ) | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:369:19:369:20 | C2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:369:19:369:24 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:370:1:370:25 | call to pattern_dispatch | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:370:1:370:25 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:370:18:370:25 | ( ... ) | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:370:19:370:20 | C3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:370:19:370:24 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:372:1:372:2 | C3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:372:1:372:6 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:372:1:372:18 | call to return_self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:372:1:372:27 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:374:1:378:3 | add_singleton | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:374:19:374:19 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:374:19:374:19 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:375:5:377:7 | instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:375:9:375:9 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:376:9:376:28 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:376:9:376:28 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:376:14:376:28 | "instance_on x" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:376:15:376:27 | instance_on x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:380:1:380:2 | c3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:380:1:380:11 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:380:6:380:7 | C1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:380:6:380:11 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:381:1:381:16 | call to add_singleton | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:381:1:381:16 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:381:15:381:16 | c3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:382:1:382:2 | c3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:382:1:382:11 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:383:1:383:2 | c3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:383:1:383:14 | call to return_self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:383:1:383:23 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:385:1:413:3 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:386:5:398:7 | class << ... | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:386:14:386:17 | self | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:387:9:389:11 | singleton1 | calls.rb:386:5:398:7 | class << ... | +| calls.rb:388:13:388:48 | call to puts | calls.rb:386:5:398:7 | class << ... | +| calls.rb:388:13:388:48 | self | calls.rb:386:5:398:7 | class << ... | +| calls.rb:388:18:388:48 | "SingletonOverride1#singleton1" | calls.rb:386:5:398:7 | class << ... | +| calls.rb:388:19:388:47 | SingletonOverride1#singleton1 | calls.rb:386:5:398:7 | class << ... | +| calls.rb:391:9:393:11 | call_singleton1 | calls.rb:386:5:398:7 | class << ... | +| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:386:5:398:7 | class << ... | +| calls.rb:392:13:392:22 | self | calls.rb:386:5:398:7 | class << ... | +| calls.rb:395:9:397:11 | factory | calls.rb:386:5:398:7 | class << ... | +| calls.rb:396:13:396:16 | self | calls.rb:386:5:398:7 | class << ... | +| calls.rb:396:13:396:20 | call to new | calls.rb:386:5:398:7 | class << ... | +| calls.rb:396:13:396:30 | call to instance1 | calls.rb:386:5:398:7 | class << ... | +| calls.rb:400:5:402:7 | singleton2 | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:400:9:400:12 | self | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:401:9:401:44 | call to puts | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:401:9:401:44 | self | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:401:14:401:44 | "SingletonOverride1#singleton2" | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:401:15:401:43 | SingletonOverride1#singleton2 | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:404:5:406:7 | call_singleton2 | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:404:9:404:12 | self | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:405:9:405:18 | call to singleton2 | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:405:9:405:18 | self | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:408:5:408:14 | call to singleton2 | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:408:5:408:14 | self | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:410:5:412:7 | instance1 | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:411:9:411:43 | call to puts | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:411:9:411:43 | self | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:411:14:411:43 | "SingletonOverride1#instance1" | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:411:15:411:42 | SingletonOverride1#instance1 | calls.rb:385:1:413:3 | SingletonOverride1 | +| calls.rb:415:1:415:18 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:415:1:415:29 | call to singleton1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:416:1:416:18 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:416:1:416:29 | call to singleton2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:417:1:417:18 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:417:1:417:34 | call to call_singleton1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:418:1:418:18 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:418:1:418:34 | call to call_singleton2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:420:1:434:3 | SingletonOverride2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:420:28:420:45 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:421:5:425:7 | class << ... | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:421:14:421:17 | self | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:422:9:424:11 | singleton1 | calls.rb:421:5:425:7 | class << ... | +| calls.rb:423:13:423:48 | call to puts | calls.rb:421:5:425:7 | class << ... | +| calls.rb:423:13:423:48 | self | calls.rb:421:5:425:7 | class << ... | +| calls.rb:423:18:423:48 | "SingletonOverride2#singleton1" | calls.rb:421:5:425:7 | class << ... | +| calls.rb:423:19:423:47 | SingletonOverride2#singleton1 | calls.rb:421:5:425:7 | class << ... | +| calls.rb:427:5:429:7 | singleton2 | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:427:9:427:12 | self | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:428:9:428:44 | call to puts | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:428:9:428:44 | self | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:428:14:428:44 | "SingletonOverride2#singleton2" | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:428:15:428:43 | SingletonOverride2#singleton2 | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:431:5:433:7 | instance1 | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:432:9:432:43 | call to puts | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:432:9:432:43 | self | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:432:14:432:43 | "SingletonOverride2#instance1" | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:432:15:432:42 | SingletonOverride2#instance1 | calls.rb:420:1:434:3 | SingletonOverride2 | +| calls.rb:436:1:436:18 | SingletonOverride2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:436:1:436:29 | call to singleton1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:437:1:437:18 | SingletonOverride2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:437:1:437:29 | call to singleton2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:438:1:438:18 | SingletonOverride2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:438:1:438:34 | call to call_singleton1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:439:1:439:18 | SingletonOverride2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:439:1:439:34 | call to call_singleton2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:441:1:469:3 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:442:5:446:7 | if ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:442:8:442:13 | call to rand | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:442:8:442:13 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:442:8:442:17 | ... > ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:442:17:442:17 | 0 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:442:19:445:11 | then ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:443:9:445:11 | m1 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:444:13:444:48 | call to puts | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:444:13:444:48 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:444:18:444:48 | "ConditionalInstanceMethods#m1" | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:444:19:444:47 | ConditionalInstanceMethods#m1 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:448:5:460:7 | m2 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:449:9:449:44 | call to puts | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:449:9:449:44 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:449:14:449:44 | "ConditionalInstanceMethods#m2" | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:449:15:449:43 | ConditionalInstanceMethods#m2 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:451:9:457:11 | m3 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:452:13:452:48 | call to puts | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:452:13:452:48 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:452:18:452:48 | "ConditionalInstanceMethods#m3" | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:452:19:452:47 | ConditionalInstanceMethods#m3 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:454:13:456:15 | m4 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:455:17:455:52 | call to puts | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:455:17:455:52 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:455:22:455:52 | "ConditionalInstanceMethods#m4" | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:455:23:455:51 | ConditionalInstanceMethods#m4 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:459:9:459:10 | call to m3 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:459:9:459:10 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:462:5:468:7 | if ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:462:8:462:13 | call to rand | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:462:8:462:13 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:462:8:462:17 | ... > ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:462:17:462:17 | 0 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:462:19:467:18 | then ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:463:9:463:13 | Class | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:463:9:467:11 | call to new | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:463:9:467:15 | call to new | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:463:9:467:18 | call to m5 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:463:19:467:11 | do ... end | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:464:13:466:15 | m5 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:465:17:465:40 | call to puts | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:465:17:465:40 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:465:22:465:40 | "AnonymousClass#m5" | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:465:23:465:39 | AnonymousClass#m5 | calls.rb:441:1:469:3 | ConditionalInstanceMethods | +| calls.rb:471:1:471:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:471:1:471:30 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:471:1:471:33 | call to m1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:472:1:472:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:472:1:472:30 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:472:1:472:33 | call to m3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:473:1:473:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:473:1:473:30 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:473:1:473:33 | call to m2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:474:1:474:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:474:1:474:30 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:474:1:474:33 | call to m3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:475:1:475:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:475:1:475:30 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:475:1:475:33 | call to m4 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:476:1:476:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:476:1:476:30 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:476:1:476:33 | call to m5 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:478:1:478:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:478:1:496:3 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:478:27:478:31 | Class | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:478:27:496:3 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:478:37:496:3 | do ... end | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:479:5:479:11 | Array | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:479:5:479:11 | [...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:479:5:479:11 | call to [] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:479:5:483:7 | call to each | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:479:6:479:6 | 0 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:479:8:479:8 | 1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:479:10:479:10 | 2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:479:18:483:7 | do ... end | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:480:9:482:11 | foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:481:13:481:22 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:481:13:481:22 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:481:18:481:22 | "foo" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:481:19:481:21 | foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:485:5:485:9 | Class | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:485:5:489:7 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:485:5:489:11 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:485:5:489:15 | call to bar | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:485:15:489:7 | do ... end | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:486:9:488:11 | bar | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:487:13:487:22 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:487:13:487:22 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:487:18:487:22 | "bar" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:487:19:487:21 | bar | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:491:5:491:11 | Array | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:491:5:491:11 | [...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:491:5:491:11 | call to [] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:491:5:495:7 | call to each | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:491:6:491:6 | 0 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:491:8:491:8 | 1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:491:10:491:10 | 2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:491:18:495:7 | do ... end | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:491:22:491:22 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:491:22:491:22 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:492:9:494:11 | call to define_method | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:492:9:494:11 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:492:23:492:32 | "baz_#{...}" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:492:24:492:27 | baz_ | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:492:28:492:31 | #{...} | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:492:30:492:30 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:492:35:494:11 | do ... end | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:493:13:493:27 | call to puts | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:493:13:493:27 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:493:18:493:27 | "baz_#{...}" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:493:19:493:22 | baz_ | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:493:23:493:26 | #{...} | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:493:25:493:25 | i | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:498:1:498:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:498:1:498:27 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:498:1:498:31 | call to foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:499:1:499:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:499:1:499:27 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:499:1:499:31 | call to bar | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:500:1:500:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:500:1:500:27 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:500:1:500:33 | call to baz_0 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:501:1:501:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:501:1:501:27 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:501:1:501:33 | call to baz_1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:502:1:502:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:502:1:502:27 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:502:1:502:33 | call to baz_2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:504:1:510:3 | ExtendSingletonMethod | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:505:5:507:7 | singleton | calls.rb:504:1:510:3 | ExtendSingletonMethod | +| calls.rb:506:9:506:46 | call to puts | calls.rb:504:1:510:3 | ExtendSingletonMethod | +| calls.rb:506:9:506:46 | self | calls.rb:504:1:510:3 | ExtendSingletonMethod | +| calls.rb:506:14:506:46 | "ExtendSingletonMethod#singleton" | calls.rb:504:1:510:3 | ExtendSingletonMethod | +| calls.rb:506:15:506:45 | ExtendSingletonMethod#singleton | calls.rb:504:1:510:3 | ExtendSingletonMethod | +| calls.rb:509:5:509:15 | call to extend | calls.rb:504:1:510:3 | ExtendSingletonMethod | +| calls.rb:509:5:509:15 | self | calls.rb:504:1:510:3 | ExtendSingletonMethod | +| calls.rb:509:12:509:15 | self | calls.rb:504:1:510:3 | ExtendSingletonMethod | +| calls.rb:512:1:512:21 | ExtendSingletonMethod | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:512:1:512:31 | call to singleton | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:514:1:516:3 | ExtendSingletonMethod2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:515:5:515:32 | call to extend | calls.rb:514:1:516:3 | ExtendSingletonMethod2 | +| calls.rb:515:5:515:32 | self | calls.rb:514:1:516:3 | ExtendSingletonMethod2 | +| calls.rb:515:12:515:32 | ExtendSingletonMethod | calls.rb:514:1:516:3 | ExtendSingletonMethod2 | +| calls.rb:518:1:518:22 | ExtendSingletonMethod2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:518:1:518:32 | call to singleton | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:520:1:521:3 | ExtendSingletonMethod3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:523:1:523:22 | ExtendSingletonMethod3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:523:1:523:51 | call to extend | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:523:31:523:51 | ExtendSingletonMethod | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:525:1:525:22 | ExtendSingletonMethod3 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:525:1:525:32 | call to singleton | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:527:1:527:3 | foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:527:1:527:13 | ... = ... | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:527:7:527:13 | "hello" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:527:8:527:12 | hello | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:528:1:528:3 | foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:528:1:528:13 | call to singleton | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:529:1:529:3 | foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:529:1:529:32 | call to extend | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:529:12:529:32 | ExtendSingletonMethod | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:531:1:531:3 | foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:531:1:531:13 | call to singleton | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:533:1:537:3 | ProtectedMethodInModule | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:534:5:536:7 | call to protected | calls.rb:533:1:537:3 | ProtectedMethodInModule | +| calls.rb:534:5:536:7 | self | calls.rb:533:1:537:3 | ProtectedMethodInModule | +| calls.rb:534:15:536:7 | foo | calls.rb:533:1:537:3 | ProtectedMethodInModule | +| calls.rb:535:9:535:42 | call to puts | calls.rb:533:1:537:3 | ProtectedMethodInModule | +| calls.rb:535:9:535:42 | self | calls.rb:533:1:537:3 | ProtectedMethodInModule | +| calls.rb:535:14:535:42 | "ProtectedMethodInModule#foo" | calls.rb:533:1:537:3 | ProtectedMethodInModule | +| calls.rb:535:15:535:41 | ProtectedMethodInModule#foo | calls.rb:533:1:537:3 | ProtectedMethodInModule | +| calls.rb:539:1:552:3 | ProtectedMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:540:5:540:35 | call to include | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:540:5:540:35 | self | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:540:13:540:35 | ProtectedMethodInModule | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:542:5:544:7 | call to protected | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:542:5:544:7 | self | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:542:15:544:7 | bar | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:543:9:543:35 | call to puts | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:543:9:543:35 | self | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:543:14:543:35 | "ProtectedMethods#bar" | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:543:15:543:34 | ProtectedMethods#bar | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:546:5:551:7 | baz | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:547:9:547:11 | call to foo | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:547:9:547:11 | self | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:548:9:548:11 | call to bar | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:548:9:548:11 | self | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:549:9:549:24 | ProtectedMethods | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:549:9:549:28 | call to new | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:549:9:549:32 | call to foo | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:550:9:550:24 | ProtectedMethods | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:550:9:550:28 | call to new | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:550:9:550:32 | call to bar | calls.rb:539:1:552:3 | ProtectedMethods | +| calls.rb:554:1:554:16 | ProtectedMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:554:1:554:20 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:554:1:554:24 | call to foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:555:1:555:16 | ProtectedMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:555:1:555:20 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:555:1:555:24 | call to bar | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:556:1:556:16 | ProtectedMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:556:1:556:20 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:556:1:556:24 | call to baz | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:558:1:563:3 | ProtectedMethodsSub | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:558:29:558:44 | ProtectedMethods | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:559:5:562:7 | baz | calls.rb:558:1:563:3 | ProtectedMethodsSub | +| calls.rb:560:9:560:11 | call to foo | calls.rb:558:1:563:3 | ProtectedMethodsSub | +| calls.rb:560:9:560:11 | self | calls.rb:558:1:563:3 | ProtectedMethodsSub | +| calls.rb:561:9:561:27 | ProtectedMethodsSub | calls.rb:558:1:563:3 | ProtectedMethodsSub | +| calls.rb:561:9:561:31 | call to new | calls.rb:558:1:563:3 | ProtectedMethodsSub | +| calls.rb:561:9:561:35 | call to foo | calls.rb:558:1:563:3 | ProtectedMethodsSub | +| calls.rb:565:1:565:19 | ProtectedMethodsSub | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:565:1:565:23 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:565:1:565:27 | call to foo | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:566:1:566:19 | ProtectedMethodsSub | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:566:1:566:23 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:566:1:566:27 | call to bar | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:567:1:567:19 | ProtectedMethodsSub | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:567:1:567:23 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:567:1:567:27 | call to baz | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:1:569:7 | Array | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:1:569:7 | [...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:1:569:7 | call to [] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:1:569:26 | call to each | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:2:569:2 | C | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:2:569:6 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:14:569:26 | { ... } | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:17:569:17 | c | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:17:569:17 | c | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:20:569:20 | c | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:569:20:569:24 | call to baz | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:1:570:13 | Array | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:1:570:13 | [...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:1:570:13 | call to [] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:1:570:39 | call to each | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:2:570:4 | "a" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:3:570:3 | a | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:6:570:8 | "b" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:7:570:7 | b | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:10:570:12 | "c" | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:11:570:11 | c | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:20:570:39 | { ... } | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:23:570:23 | s | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:23:570:23 | s | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:26:570:26 | s | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:570:26:570:37 | call to capitalize | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:572:1:575:3 | SingletonUpCall_Base | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:573:5:574:7 | singleton | calls.rb:572:1:575:3 | SingletonUpCall_Base | +| calls.rb:573:9:573:12 | self | calls.rb:572:1:575:3 | SingletonUpCall_Base | +| calls.rb:576:1:583:3 | SingletonUpCall_Sub | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:576:29:576:48 | SingletonUpCall_Base | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:577:5:577:13 | call to singleton | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:577:5:577:13 | self | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:578:5:578:14 | call to singleton2 | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:578:5:578:14 | self | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:579:5:582:7 | mid_method | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:579:9:579:12 | self | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:580:9:580:17 | call to singleton | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:580:9:580:17 | self | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:581:9:581:18 | call to singleton2 | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:581:9:581:18 | self | calls.rb:576:1:583:3 | SingletonUpCall_Sub | +| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:584:32:584:50 | SingletonUpCall_Sub | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:585:5:586:7 | singleton2 | calls.rb:584:1:589:3 | SingletonUpCall_SubSub | +| calls.rb:585:9:585:12 | self | calls.rb:584:1:589:3 | SingletonUpCall_SubSub | +| calls.rb:588:5:588:14 | call to mid_method | calls.rb:584:1:589:3 | SingletonUpCall_SubSub | +| calls.rb:588:5:588:14 | self | calls.rb:584:1:589:3 | SingletonUpCall_SubSub | +| calls.rb:591:1:602:3 | SingletonA | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:592:5:593:7 | singleton1 | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:592:9:592:12 | self | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:595:5:597:7 | call_singleton1 | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:595:9:595:12 | self | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:596:9:596:18 | self | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:599:5:601:7 | call_call_singleton1 | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:599:9:599:12 | self | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:600:9:600:23 | self | calls.rb:591:1:602:3 | SingletonA | +| calls.rb:604:1:611:3 | SingletonB | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:604:20:604:29 | SingletonA | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:605:5:606:7 | singleton1 | calls.rb:604:1:611:3 | SingletonB | +| calls.rb:605:9:605:12 | self | calls.rb:604:1:611:3 | SingletonB | +| calls.rb:608:5:610:7 | call_singleton1 | calls.rb:604:1:611:3 | SingletonB | +| calls.rb:608:9:608:12 | self | calls.rb:604:1:611:3 | SingletonB | +| calls.rb:609:9:609:18 | call to singleton1 | calls.rb:604:1:611:3 | SingletonB | +| calls.rb:609:9:609:18 | self | calls.rb:604:1:611:3 | SingletonB | +| calls.rb:613:1:620:3 | SingletonC | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:613:20:613:29 | SingletonA | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:614:5:615:7 | singleton1 | calls.rb:613:1:620:3 | SingletonC | +| calls.rb:614:9:614:12 | self | calls.rb:613:1:620:3 | SingletonC | +| calls.rb:617:5:619:7 | call_singleton1 | calls.rb:613:1:620:3 | SingletonC | +| calls.rb:617:9:617:12 | self | calls.rb:613:1:620:3 | SingletonC | +| calls.rb:618:9:618:18 | call to singleton1 | calls.rb:613:1:620:3 | SingletonC | +| calls.rb:618:9:618:18 | self | calls.rb:613:1:620:3 | SingletonC | +| calls.rb:622:1:622:10 | SingletonA | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:622:1:622:31 | call to call_call_singleton1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:623:1:623:10 | SingletonB | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:623:1:623:31 | call to call_call_singleton1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:624:1:624:10 | SingletonC | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:624:1:624:31 | call to call_call_singleton1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:626:1:632:3 | Included | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:627:5:629:7 | foo | calls.rb:626:1:632:3 | Included | +| calls.rb:628:9:628:12 | self | calls.rb:626:1:632:3 | Included | +| calls.rb:628:9:628:16 | call to bar | calls.rb:626:1:632:3 | Included | +| calls.rb:630:5:631:7 | bar | calls.rb:626:1:632:3 | Included | +| calls.rb:634:1:639:3 | IncludesIncluded | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:635:5:635:20 | call to include | calls.rb:634:1:639:3 | IncludesIncluded | +| calls.rb:635:5:635:20 | self | calls.rb:634:1:639:3 | IncludesIncluded | +| calls.rb:635:13:635:20 | Included | calls.rb:634:1:639:3 | IncludesIncluded | +| calls.rb:636:5:638:7 | bar | calls.rb:634:1:639:3 | IncludesIncluded | +| calls.rb:637:9:637:13 | super call to bar | calls.rb:634:1:639:3 | IncludesIncluded | +| calls.rb:641:1:645:3 | CustomNew1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:642:5:644:7 | new | calls.rb:641:1:645:3 | CustomNew1 | +| calls.rb:642:9:642:12 | self | calls.rb:641:1:645:3 | CustomNew1 | +| calls.rb:643:9:643:10 | C1 | calls.rb:641:1:645:3 | CustomNew1 | +| calls.rb:643:9:643:14 | call to new | calls.rb:641:1:645:3 | CustomNew1 | +| calls.rb:647:1:647:10 | CustomNew1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:647:1:647:14 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:647:1:647:23 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:649:1:657:3 | CustomNew2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:650:5:652:7 | new | calls.rb:649:1:657:3 | CustomNew2 | +| calls.rb:650:9:650:12 | self | calls.rb:649:1:657:3 | CustomNew2 | +| calls.rb:651:9:651:12 | self | calls.rb:649:1:657:3 | CustomNew2 | +| calls.rb:651:9:651:21 | call to allocate | calls.rb:649:1:657:3 | CustomNew2 | +| calls.rb:654:5:656:7 | instance | calls.rb:649:1:657:3 | CustomNew2 | +| calls.rb:655:9:655:34 | call to puts | calls.rb:649:1:657:3 | CustomNew2 | +| calls.rb:655:9:655:34 | self | calls.rb:649:1:657:3 | CustomNew2 | +| calls.rb:655:14:655:34 | "CustomNew2#instance" | calls.rb:649:1:657:3 | CustomNew2 | +| calls.rb:655:15:655:33 | CustomNew2#instance | calls.rb:649:1:657:3 | CustomNew2 | +| calls.rb:659:1:659:10 | CustomNew2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:659:1:659:14 | call to new | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:659:1:659:23 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:661:1:665:3 | capture_parameter | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:661:23:661:23 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:661:23:661:23 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:662:5:662:11 | Array | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:662:5:662:11 | [...] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:662:5:662:11 | call to [] | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:662:5:664:7 | call to each | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:662:6:662:6 | 0 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:662:8:662:8 | 1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:662:10:662:10 | 2 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:662:18:664:7 | do ... end | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:663:9:663:9 | x | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:667:1:667:26 | ( ... ) | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:667:1:667:35 | call to instance | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:667:2:667:25 | call to capture_parameter | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:667:2:667:25 | self | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:667:20:667:21 | C1 | calls.rb:1:1:667:52 | calls.rb | +| calls.rb:667:20:667:25 | call to new | calls.rb:1:1:667:52 | calls.rb | | hello.rb:1:1:8:3 | EnglishWords | hello.rb:1:1:22:3 | hello.rb | | hello.rb:2:5:4:7 | hello | hello.rb:1:1:8:3 | EnglishWords | | hello.rb:3:9:3:22 | return | hello.rb:1:1:8:3 | EnglishWords | diff --git a/ruby/ql/test/library-tests/modules/superclasses.expected b/ruby/ql/test/library-tests/modules/superclasses.expected index a2c3473098b..358fe7fb4e9 100644 --- a/ruby/ql/test/library-tests/modules/superclasses.expected +++ b/ruby/ql/test/library-tests/modules/superclasses.expected @@ -90,62 +90,62 @@ calls.rb: # 325| C1 #-----| -> Object -# 331| C2 +# 335| C2 #-----| -> C1 -# 337| C3 +# 341| C3 #-----| -> C2 -# 377| SingletonOverride1 +# 385| SingletonOverride1 #-----| -> Object -# 412| SingletonOverride2 +# 420| SingletonOverride2 #-----| -> SingletonOverride1 -# 433| ConditionalInstanceMethods +# 441| ConditionalInstanceMethods #-----| -> Object -# 496| ExtendSingletonMethod +# 504| ExtendSingletonMethod -# 506| ExtendSingletonMethod2 +# 514| ExtendSingletonMethod2 -# 512| ExtendSingletonMethod3 +# 520| ExtendSingletonMethod3 -# 525| ProtectedMethodInModule +# 533| ProtectedMethodInModule -# 531| ProtectedMethods +# 539| ProtectedMethods #-----| -> Object -# 550| ProtectedMethodsSub +# 558| ProtectedMethodsSub #-----| -> ProtectedMethods -# 564| SingletonUpCall_Base +# 572| SingletonUpCall_Base #-----| -> Object -# 568| SingletonUpCall_Sub +# 576| SingletonUpCall_Sub #-----| -> SingletonUpCall_Base -# 576| SingletonUpCall_SubSub +# 584| SingletonUpCall_SubSub #-----| -> SingletonUpCall_Sub -# 583| SingletonA +# 591| SingletonA #-----| -> Object -# 596| SingletonB +# 604| SingletonB #-----| -> SingletonA -# 605| SingletonC +# 613| SingletonC #-----| -> SingletonA -# 618| Included +# 626| Included -# 626| IncludesIncluded +# 634| IncludesIncluded #-----| -> Object -# 633| CustomNew1 +# 641| CustomNew1 #-----| -> Object -# 641| CustomNew2 +# 649| CustomNew2 #-----| -> Object hello.rb: diff --git a/shared/regex/qlpack.yml b/shared/regex/qlpack.yml index bd61542e004..ef9519ead25 100644 --- a/shared/regex/qlpack.yml +++ b/shared/regex/qlpack.yml @@ -3,3 +3,4 @@ version: 0.0.13-dev groups: shared library: true dependencies: +warnOnImplicitThis: true diff --git a/shared/ssa/qlpack.yml b/shared/ssa/qlpack.yml index 6c1e42e1950..4bb3d04e800 100644 --- a/shared/ssa/qlpack.yml +++ b/shared/ssa/qlpack.yml @@ -2,3 +2,4 @@ name: codeql/ssa version: 0.0.17-dev groups: shared library: true +warnOnImplicitThis: true diff --git a/shared/tutorial/qlpack.yml b/shared/tutorial/qlpack.yml index 4ac2f206cba..37c2fca38b4 100644 --- a/shared/tutorial/qlpack.yml +++ b/shared/tutorial/qlpack.yml @@ -3,3 +3,4 @@ description: Library for the CodeQL detective tutorials, helping new users learn version: 0.0.10-dev groups: shared library: true +warnOnImplicitThis: true diff --git a/shared/typetracking/qlpack.yml b/shared/typetracking/qlpack.yml index 239091ead67..499f5cc4d34 100644 --- a/shared/typetracking/qlpack.yml +++ b/shared/typetracking/qlpack.yml @@ -4,3 +4,4 @@ groups: shared library: true dependencies: codeql/util: ${workspace} +warnOnImplicitThis: true diff --git a/shared/typos/qlpack.yml b/shared/typos/qlpack.yml index 7f7a802dd0b..6d0b76e1ce5 100644 --- a/shared/typos/qlpack.yml +++ b/shared/typos/qlpack.yml @@ -2,3 +2,4 @@ name: codeql/typos version: 0.0.17-dev groups: shared library: true +warnOnImplicitThis: true diff --git a/shared/util/qlpack.yml b/shared/util/qlpack.yml index f3f03fded40..8ff9a0efdb6 100644 --- a/shared/util/qlpack.yml +++ b/shared/util/qlpack.yml @@ -3,3 +3,4 @@ version: 0.0.10-dev groups: shared library: true dependencies: +warnOnImplicitThis: true diff --git a/shared/yaml/qlpack.yml b/shared/yaml/qlpack.yml index f08abe18bfc..75a796f2ba3 100644 --- a/shared/yaml/qlpack.yml +++ b/shared/yaml/qlpack.yml @@ -2,3 +2,4 @@ name: codeql/yaml version: 0.0.2-dev groups: shared library: true +warnOnImplicitThis: true diff --git a/swift/actions/build-and-test/action.yml b/swift/actions/build-and-test/action.yml index 2e084e9a97b..f800bd3ffc2 100644 --- a/swift/actions/build-and-test/action.yml +++ b/swift/actions/build-and-test/action.yml @@ -53,21 +53,16 @@ runs: shell: bash run: | bazel run //swift:create-extractor-pack - - name: Run xcode-autobuilder tests - if : ${{ github.event_name == 'pull_request' && runner.os == 'macOS' }} - shell: bash - run: | - bazel test //swift/xcode-autobuilder/tests - name: Run codegen tests if : ${{ github.event_name == 'pull_request' }} shell: bash run: | - bazel test //misc/codegen/test - - name: Run qltest tests - if : ${{ github.event_name == 'pull_request' }} + bazel test //misc/codegen/... + - name: Run Swift tests + if: ${{ github.event_name == 'pull_request' }} shell: bash run: | - bazel test //swift/tools/test/qltest + bazel test //swift/... - name: Evict bazel cache if: ${{ github.event_name != 'pull_request' }} shell: bash diff --git a/swift/codeql-extractor.yml b/swift/codeql-extractor.yml index 94a63897697..0439f0ea3e0 100644 --- a/swift/codeql-extractor.yml +++ b/swift/codeql-extractor.yml @@ -1,6 +1,6 @@ name: "swift" display_name: "Swift" -version: 0.0.1 +version: 0.1.0 column_kind: "utf8" legacy_qltest_extraction: true github_api_languages: diff --git a/swift/integration-tests/linux-only/autobuilder/unsupported-os/diagnostics.expected b/swift/integration-tests/linux-only/autobuilder/unsupported-os/diagnostics.expected index 6b5e3b71bbc..2d3c70daab3 100644 --- a/swift/integration-tests/linux-only/autobuilder/unsupported-os/diagnostics.expected +++ b/swift/integration-tests/linux-only/autobuilder/unsupported-os/diagnostics.expected @@ -1,15 +1,13 @@ { "helpLinks": [ - "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on", - "https://docs.github.com/en/enterprise-server/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning", - "https://docs.github.com/en/enterprise-server/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language" + "" ], - "plaintextMessage": "CodeQL Swift analysis is currently only officially supported on macOS.\n\nChange the action runner to a macOS one. Analysis on Linux might work, but requires setting up a custom build command.", + "markdownMessage": "Currently, `autobuild` for Swift analysis is only supported on macOS.\n\n[Change the Actions runner][1] to run on macOS.\n\nYou may be able to run analysis on Linux by setting up a [manual build command][2].\n\n[1]: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on\n[2]: https://docs.github.com/en/enterprise-server/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language", "severity": "error", "source": { "extractorName": "swift", "id": "swift/autobuilder/incompatible-os", - "name": "Incompatible operating system for autobuild (expected macOS)" + "name": "Incompatible operating system (expected macOS)" }, "visibility": { "cliSummaryTable": true, diff --git a/swift/logging/SwiftDiagnostics.cpp b/swift/logging/SwiftDiagnostics.cpp index 4c490486a26..06c86f7f58a 100644 --- a/swift/logging/SwiftDiagnostics.cpp +++ b/swift/logging/SwiftDiagnostics.cpp @@ -8,6 +8,22 @@ namespace codeql { +namespace { +std::string_view severityToString(SwiftDiagnostic::Severity severity) { + using S = SwiftDiagnostic::Severity; + switch (severity) { + case S::note: + return "note"; + case S::warning: + return "warning"; + case S::error: + return "error"; + default: + return "unknown"; + } +} +} // namespace + nlohmann::json SwiftDiagnostic::json(const std::chrono::system_clock::time_point& timestamp, std::string_view message) const { nlohmann::json ret{ @@ -23,9 +39,10 @@ nlohmann::json SwiftDiagnostic::json(const std::chrono::system_clock::time_point {"cliSummaryTable", has(Visibility::cliSummaryTable)}, {"telemetry", has(Visibility::telemetry)}, }}, - {"severity", "error"}, + {"severity", severityToString(severity)}, {"helpLinks", std::vector(absl::StrSplit(helpLinks, ' '))}, - {"plaintextMessage", absl::StrCat(message, ".\n\n", action, ".")}, + {format == Format::markdown ? "markdownMessage" : "plaintextMessage", + absl::StrCat(message, ".\n\n", action)}, {"timestamp", fmt::format("{:%FT%T%z}", timestamp)}, }; if (location) { diff --git a/swift/logging/SwiftDiagnostics.h b/swift/logging/SwiftDiagnostics.h index 6e539b0330b..5a0f5617076 100644 --- a/swift/logging/SwiftDiagnostics.h +++ b/swift/logging/SwiftDiagnostics.h @@ -33,6 +33,11 @@ struct SwiftDiagnosticsLocation { // These are internally stored into a map on id's. A specific error log can use binlog's category // as id, which will then be used to recover the diagnostic source while dumping. struct SwiftDiagnostic { + enum class Format { + plaintext, + markdown, + }; + enum class Visibility : unsigned char { none = 0b000, statusPage = 0b001, @@ -41,33 +46,53 @@ struct SwiftDiagnostic { all = 0b111, }; + // Notice that Tool Status Page severity is not necessarily the same as log severity, as the + // scope is different: TSP's scope is the whole analysis, log's scope is a single run + enum class Severity { + note, + warning, + error, + }; + + // wrapper for passing optional help links to constructor + struct HelpLinks { + std::string_view value; + }; + + static constexpr std::string_view extractorName = "swift"; + std::string_view id; std::string_view name; - static constexpr std::string_view extractorName = "swift"; std::string_view action; + + Format format{Format::markdown}; + Visibility visibility{Visibility::all}; + Severity severity{Severity::error}; + // space separated if more than 1. Not a vector to allow constexpr // TODO(C++20) with vector going constexpr this can be turned to `std::vector` - std::string_view helpLinks; - // for the moment, we only output errors, so no need to store the severity - - Visibility visibility{Visibility::all}; + std::string_view helpLinks{""}; std::optional location{}; + // notice help links are really required only for plaintext messages, otherwise they should be + // directly embedded in the markdown message + // optional arguments can be any of HelpLinks, Severity, Visibility or Format to set the + // corresponding field + // TODO(C++20) this constructor won't really be necessary anymore with designated initializers + template constexpr SwiftDiagnostic(std::string_view id, std::string_view name, - std::string_view action = "", - std::string_view helpLinks = "", - Visibility visibility = Visibility::all) - : id{id}, name{name}, action{action}, helpLinks{helpLinks}, visibility{visibility} {} + std::string_view action, + OptionalArgs... optionalArgs) + : id{id}, name{name}, action{action} { + (setOptionalArg(optionalArgs), ...); + } - constexpr SwiftDiagnostic(std::string_view id, std::string_view name, Visibility visibility) - : SwiftDiagnostic(id, name, "", "", visibility) {} - - // create a JSON diagnostics for this source with the given timestamp and message to out - // A plaintextMessage is used that includes both the message and the action to take. Dots are - // appended to both. The id is used to construct the source id in the form - // `swift//` + // create a JSON diagnostics for this source with the given `timestamp` and `message` + // Depending on format, either a plaintextMessage or markdownMessage is used that includes both + // the message and the action to take. A dot '.' is appended to `message`. The id is used to + // construct the source id in the form `swift//` nlohmann::json json(const std::chrono::system_clock::time_point& timestamp, std::string_view message) const; @@ -86,6 +111,15 @@ struct SwiftDiagnostic { private: bool has(Visibility v) const; + + constexpr void setOptionalArg(HelpLinks h) { helpLinks = h.value; } + constexpr void setOptionalArg(Format f) { format = f; } + constexpr void setOptionalArg(Visibility v) { visibility = v; } + constexpr void setOptionalArg(Severity s) { severity = s; } + + // intentionally left undefined + template + constexpr void setOptionalArg(T); }; inline constexpr SwiftDiagnostic::Visibility operator|(SwiftDiagnostic::Visibility lhs, @@ -103,6 +137,12 @@ inline constexpr SwiftDiagnostic::Visibility operator&(SwiftDiagnostic::Visibili constexpr SwiftDiagnostic internalError{ "internal-error", "Internal error", - SwiftDiagnostic::Visibility::telemetry, + "Some or all of the Swift analysis may have failed.\n" + "\n" + "If the error persists, contact support, quoting the error message and describing what " + "happened, or [open an issue in our open source repository][1].\n" + "\n" + "[1]: https://github.com/github/codeql/issues/new?labels=bug&template=ql---general.md", + SwiftDiagnostic::Severity::warning, }; } // namespace codeql diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll index 74779ea3b37..a52ddb6f8bd 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll @@ -33,7 +33,7 @@ class Node extends TNode { } /** - * Gets this node's underlying expression, if any. + * Gets the expression that corresponds to this node, if any. */ Expr asExpr() { none() } @@ -43,7 +43,7 @@ class Node extends TNode { Pattern asPattern() { none() } /** - * Gets this data flow node's corresponding control flow node. + * Gets the control flow node that corresponds to this data flow node. */ ControlFlowNode getCfgNode() { none() } diff --git a/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll index 1adc157fb6f..8f36a95e99d 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll @@ -29,6 +29,18 @@ private class DefaultCleartextLoggingSink extends CleartextLoggingSink { DefaultCleartextLoggingSink() { sinkNode(this, "log-injection") } } +/** + * An barrier for cleartext logging vulnerabilities. + * - encryption; encrypted values are not cleartext. + * - booleans; these are more likely to be settings, rather than actual sensitive data. + */ +private class CleartextLoggingDefaultBarrier extends CleartextLoggingBarrier { + CleartextLoggingDefaultBarrier() { + this.asExpr() instanceof EncryptedExpr or + this.asExpr().getType().getUnderlyingType() instanceof BoolType + } +} + /** * A barrier for `OSLogMessage`s configured with the appropriate privacy option. * Numeric and boolean arguments aren't redacted unless the `private` or `sensitive` options are used. diff --git a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll index 4d024ced959..cb7e8c53ec8 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll @@ -114,10 +114,15 @@ private class CleartextStorageDatabaseSinks extends SinkModelCsv { } /** - * An encryption barrier for cleartext database storage vulnerabilities. + * An barrier for cleartext database storage vulnerabilities. + * - encryption; encrypted values are not cleartext. + * - booleans; these are more likely to be settings, rather than actual sensitive data. */ -private class CleartextStorageDatabaseEncryptionBarrier extends CleartextStorageDatabaseBarrier { - CleartextStorageDatabaseEncryptionBarrier() { this.asExpr() instanceof EncryptedExpr } +private class CleartextStorageDatabaseDefaultBarrier extends CleartextStorageDatabaseBarrier { + CleartextStorageDatabaseDefaultBarrier() { + this.asExpr() instanceof EncryptedExpr or + this.asExpr().getType().getUnderlyingType() instanceof BoolType + } } /** diff --git a/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll index cc7a443e8e2..b3306dabc9f 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll @@ -74,11 +74,15 @@ private class NSUserDefaultsControllerStore extends CleartextStoragePreferencesS } /** - * An encryption barrier for cleartext preferences storage vulnerabilities. + * An barrier for cleartext preferences storage vulnerabilities. + * - encryption; encrypted values are not cleartext. + * - booleans; these are more likely to be settings, rather than actual sensitive data. */ -private class CleartextStoragePreferencesEncryptionBarrier extends CleartextStoragePreferencesBarrier -{ - CleartextStoragePreferencesEncryptionBarrier() { this.asExpr() instanceof EncryptedExpr } +private class CleartextStoragePreferencesDefaultBarrier extends CleartextStoragePreferencesBarrier { + CleartextStoragePreferencesDefaultBarrier() { + this.asExpr() instanceof EncryptedExpr or + this.asExpr().getType().getUnderlyingType() instanceof BoolType + } } /** diff --git a/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll index 760a2f3500b..a9dedff2f6c 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll @@ -81,10 +81,15 @@ private class AlamofireTransmittedSink extends CleartextTransmissionSink { } /** - * An encryption barrier for cleartext transmission vulnerabilities. + * An barrier for cleartext transmission vulnerabilities. + * - encryption; encrypted values are not cleartext. + * - booleans; these are more likely to be settings, rather than actual sensitive data. */ -private class CleartextTransmissionEncryptionBarrier extends CleartextTransmissionBarrier { - CleartextTransmissionEncryptionBarrier() { this.asExpr() instanceof EncryptedExpr } +private class CleartextTransmissionDefaultBarrier extends CleartextTransmissionBarrier { + CleartextTransmissionDefaultBarrier() { + this.asExpr() instanceof EncryptedExpr or + this.asExpr().getType().getUnderlyingType() instanceof BoolType + } } /** diff --git a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll index aa66f6d93fd..91f824aa5f2 100644 --- a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll +++ b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll @@ -48,7 +48,7 @@ class SensitivePrivateInfo extends SensitiveDataType, TPrivateInfo { // Contact information, such as home addresses "post.?code|zip.?code|home.?address|" + // and telephone numbers - "telephone|home.?phone|mobile|fax.?no|fax.?number|" + + "(mob(ile)?|home).?(num|no|tel|phone)|(tel|fax).?(num|no)|telephone|" + // Geographic location - where the user is (or was) "latitude|longitude|" + // Financial data - such as credit card numbers, salary, bank accounts, and debts @@ -69,7 +69,7 @@ class SensitivePrivateInfo extends SensitiveDataType, TPrivateInfo { * contain hashed or encrypted data, or are only a reference to data that is * actually stored elsewhere. */ -private string regexpProbablySafe() { result = ".*(hash|crypt|file|path|invalid).*" } +private string regexpProbablySafe() { result = ".*(hash|crypt|file|path|url|invalid).*" } /** * A `VarDecl` that might be used to contain sensitive data. diff --git a/swift/ql/lib/qlpack.yml b/swift/ql/lib/qlpack.yml index 3cb8840e0eb..f45d347bad3 100644 --- a/swift/ql/lib/qlpack.yml +++ b/swift/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/swift-all -version: 0.0.0 +version: 0.1.0 groups: swift extractor: swift dbscheme: swift.dbscheme diff --git a/swift/ql/src/qlpack.yml b/swift/ql/src/qlpack.yml index 7e473775c1c..2a0bee06578 100644 --- a/swift/ql/src/qlpack.yml +++ b/swift/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/swift-queries -version: 0.0.0 +version: 0.1.0 groups: - swift - queries diff --git a/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift b/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift index 82ffaf3a94a..dcc273b7771 100644 --- a/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift +++ b/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift @@ -13,13 +13,16 @@ func encrypt(padding : Padding) { // GOOD: Using randomly generated keys for encryption - let key = (0..<10).map({ _ in UInt8.random(in: 0...UInt8.max) }) - let keyString = String(cString: key) - let ivString = getRandomIV() - _ = try AES(key: key, blockMode: CBC(), padding: padding) - _ = try AES(key: keyString, iv: ivString) - _ = try Blowfish(key: key, blockMode: CBC(), padding: padding) - _ = try Blowfish(key: keyString, iv: ivString) + var key = [Int8](repeating: 0, count: 10) + let status = SecRandomCopyBytes(kSecRandomDefault, key.count - 1, &key) + if status == errSecSuccess { + let keyString = String(cString: key) + let ivString = getRandomIV() + _ = try AES(key: key, blockMode: CBC(), padding: padding) + _ = try AES(key: keyString, iv: ivString) + _ = try Blowfish(key: key, blockMode: CBC(), padding: padding) + _ = try Blowfish(key: keyString, iv: ivString) + } // ... } diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected index ed65adcc9b6..94272faf6d0 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected +++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected @@ -7,11 +7,11 @@ edges | testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | | testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:33:14:33:32 | call to Data.init(_:) | | testSend.swift:41:10:41:18 | data | testSend.swift:41:45:41:45 | data | -| testSend.swift:45:13:45:13 | password | testSend.swift:52:27:52:27 | str1 | -| testSend.swift:46:13:46:13 | password | testSend.swift:53:27:53:27 | str2 | -| testSend.swift:47:13:47:25 | call to pad(_:) | testSend.swift:54:27:54:27 | str3 | -| testSend.swift:47:17:47:17 | password | testSend.swift:41:10:41:18 | data | -| testSend.swift:47:17:47:17 | password | testSend.swift:47:13:47:25 | call to pad(_:) | +| testSend.swift:52:13:52:13 | password | testSend.swift:59:27:59:27 | str1 | +| testSend.swift:53:13:53:13 | password | testSend.swift:60:27:60:27 | str2 | +| testSend.swift:54:13:54:25 | call to pad(_:) | testSend.swift:61:27:61:27 | str3 | +| testSend.swift:54:17:54:17 | password | testSend.swift:41:10:41:18 | data | +| testSend.swift:54:17:54:17 | password | testSend.swift:54:13:54:25 | call to pad(_:) | | testURL.swift:13:54:13:54 | passwd | testURL.swift:13:22:13:54 | ... .+(_:_:) ... | | testURL.swift:16:55:16:55 | credit_card_no | testURL.swift:16:22:16:55 | ... .+(_:_:) ... | nodes @@ -29,13 +29,15 @@ nodes | testSend.swift:37:19:37:19 | data2 | semmle.label | data2 | | testSend.swift:41:10:41:18 | data | semmle.label | data | | testSend.swift:41:45:41:45 | data | semmle.label | data | -| testSend.swift:45:13:45:13 | password | semmle.label | password | -| testSend.swift:46:13:46:13 | password | semmle.label | password | -| testSend.swift:47:13:47:25 | call to pad(_:) | semmle.label | call to pad(_:) | -| testSend.swift:47:17:47:17 | password | semmle.label | password | -| testSend.swift:52:27:52:27 | str1 | semmle.label | str1 | -| testSend.swift:53:27:53:27 | str2 | semmle.label | str2 | -| testSend.swift:54:27:54:27 | str3 | semmle.label | str3 | +| testSend.swift:52:13:52:13 | password | semmle.label | password | +| testSend.swift:53:13:53:13 | password | semmle.label | password | +| testSend.swift:54:13:54:25 | call to pad(_:) | semmle.label | call to pad(_:) | +| testSend.swift:54:17:54:17 | password | semmle.label | password | +| testSend.swift:59:27:59:27 | str1 | semmle.label | str1 | +| testSend.swift:60:27:60:27 | str2 | semmle.label | str2 | +| testSend.swift:61:27:61:27 | str3 | semmle.label | str3 | +| testSend.swift:65:27:65:27 | license_key | semmle.label | license_key | +| testSend.swift:66:27:66:30 | .mobileNumber | semmle.label | .mobileNumber | | testURL.swift:13:22:13:54 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | | testURL.swift:13:54:13:54 | passwd | semmle.label | passwd | | testURL.swift:16:22:16:55 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | @@ -43,16 +45,18 @@ nodes | testURL.swift:20:22:20:22 | passwd | semmle.label | passwd | subpaths | testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | testSend.swift:33:14:33:32 | call to Data.init(_:) | -| testSend.swift:47:17:47:17 | password | testSend.swift:41:10:41:18 | data | testSend.swift:41:45:41:45 | data | testSend.swift:47:13:47:25 | call to pad(_:) | +| testSend.swift:54:17:54:17 | password | testSend.swift:41:10:41:18 | data | testSend.swift:41:45:41:45 | data | testSend.swift:54:13:54:25 | call to pad(_:) | #select | testAlamofire.swift:150:13:150:45 | ... .+(_:_:) ... | testAlamofire.swift:150:45:150:45 | password | testAlamofire.swift:150:13:150:45 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testAlamofire.swift:150:45:150:45 | password | password | | testAlamofire.swift:152:19:152:51 | ... .+(_:_:) ... | testAlamofire.swift:152:51:152:51 | password | testAlamofire.swift:152:19:152:51 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testAlamofire.swift:152:51:152:51 | password | password | | testAlamofire.swift:154:14:154:46 | ... .+(_:_:) ... | testAlamofire.swift:154:38:154:38 | email | testAlamofire.swift:154:14:154:46 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testAlamofire.swift:154:38:154:38 | email | email | | testSend.swift:29:19:29:19 | passwordPlain | testSend.swift:29:19:29:19 | passwordPlain | testSend.swift:29:19:29:19 | passwordPlain | This operation transmits 'passwordPlain', which may contain unencrypted sensitive data from $@. | testSend.swift:29:19:29:19 | passwordPlain | passwordPlain | | testSend.swift:37:19:37:19 | data2 | testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:37:19:37:19 | data2 | This operation transmits 'data2', which may contain unencrypted sensitive data from $@. | testSend.swift:33:19:33:19 | passwordPlain | passwordPlain | -| testSend.swift:52:27:52:27 | str1 | testSend.swift:45:13:45:13 | password | testSend.swift:52:27:52:27 | str1 | This operation transmits 'str1', which may contain unencrypted sensitive data from $@. | testSend.swift:45:13:45:13 | password | password | -| testSend.swift:53:27:53:27 | str2 | testSend.swift:46:13:46:13 | password | testSend.swift:53:27:53:27 | str2 | This operation transmits 'str2', which may contain unencrypted sensitive data from $@. | testSend.swift:46:13:46:13 | password | password | -| testSend.swift:54:27:54:27 | str3 | testSend.swift:47:17:47:17 | password | testSend.swift:54:27:54:27 | str3 | This operation transmits 'str3', which may contain unencrypted sensitive data from $@. | testSend.swift:47:17:47:17 | password | password | +| testSend.swift:59:27:59:27 | str1 | testSend.swift:52:13:52:13 | password | testSend.swift:59:27:59:27 | str1 | This operation transmits 'str1', which may contain unencrypted sensitive data from $@. | testSend.swift:52:13:52:13 | password | password | +| testSend.swift:60:27:60:27 | str2 | testSend.swift:53:13:53:13 | password | testSend.swift:60:27:60:27 | str2 | This operation transmits 'str2', which may contain unencrypted sensitive data from $@. | testSend.swift:53:13:53:13 | password | password | +| testSend.swift:61:27:61:27 | str3 | testSend.swift:54:17:54:17 | password | testSend.swift:61:27:61:27 | str3 | This operation transmits 'str3', which may contain unencrypted sensitive data from $@. | testSend.swift:54:17:54:17 | password | password | +| testSend.swift:65:27:65:27 | license_key | testSend.swift:65:27:65:27 | license_key | testSend.swift:65:27:65:27 | license_key | This operation transmits 'license_key', which may contain unencrypted sensitive data from $@. | testSend.swift:65:27:65:27 | license_key | license_key | +| testSend.swift:66:27:66:30 | .mobileNumber | testSend.swift:66:27:66:30 | .mobileNumber | testSend.swift:66:27:66:30 | .mobileNumber | This operation transmits '.mobileNumber', which may contain unencrypted sensitive data from $@. | testSend.swift:66:27:66:30 | .mobileNumber | .mobileNumber | | testURL.swift:13:22:13:54 | ... .+(_:_:) ... | testURL.swift:13:54:13:54 | passwd | testURL.swift:13:22:13:54 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:13:54:13:54 | passwd | passwd | | testURL.swift:16:22:16:55 | ... .+(_:_:) ... | testURL.swift:16:55:16:55 | credit_card_no | testURL.swift:16:22:16:55 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:16:55:16:55 | credit_card_no | credit_card_no | | testURL.swift:20:22:20:22 | passwd | testURL.swift:20:22:20:22 | passwd | testURL.swift:20:22:20:22 | passwd | This operation transmits 'passwd', which may contain unencrypted sensitive data from $@. | testURL.swift:20:22:20:22 | passwd | passwd | diff --git a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected index ef794d4004a..20e1757c132 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected +++ b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected @@ -120,12 +120,15 @@ | testRealm.swift:73:15:73:15 | myPassword | label:myPassword, type:credential | | testSend.swift:29:19:29:19 | passwordPlain | label:passwordPlain, type:credential | | testSend.swift:33:19:33:19 | passwordPlain | label:passwordPlain, type:credential | -| testSend.swift:45:13:45:13 | password | label:password, type:credential | -| testSend.swift:46:13:46:13 | password | label:password, type:credential | -| testSend.swift:47:17:47:17 | password | label:password, type:credential | -| testSend.swift:48:23:48:23 | password | label:password, type:credential | -| testSend.swift:49:27:49:27 | password | label:password, type:credential | -| testSend.swift:50:27:50:27 | password | label:password, type:credential | +| testSend.swift:52:13:52:13 | password | label:password, type:credential | +| testSend.swift:53:13:53:13 | password | label:password, type:credential | +| testSend.swift:54:17:54:17 | password | label:password, type:credential | +| testSend.swift:55:23:55:23 | password | label:password, type:credential | +| testSend.swift:56:27:56:27 | password | label:password, type:credential | +| testSend.swift:57:27:57:27 | password | label:password, type:credential | +| testSend.swift:65:27:65:27 | license_key | label:license_key, type:credential | +| testSend.swift:66:27:66:30 | .mobileNumber | label:mobileNumber, type:private information | +| testSend.swift:69:27:69:30 | .passwordFeatureEnabled | label:passwordFeatureEnabled, type:credential | | testURL.swift:13:54:13:54 | passwd | label:passwd, type:credential | | testURL.swift:16:55:16:55 | credit_card_no | label:credit_card_no, type:private information | | testURL.swift:20:22:20:22 | passwd | label:passwd, type:credential | diff --git a/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift b/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift index 8bcf9ce83f5..94bc9e07800 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift +++ b/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift @@ -30,11 +30,11 @@ class MyRealmSwiftObject : RealmSwiftObject { class MyRealmSwiftObject2 : Object { override init() { password = "" } - var username: String? + var harmless: String? var password: String? } -func test1(realm : Realm, myUsername: String, myPassword : String, myHashedPassword : String) { +func test1(realm : Realm, myHarmless: String, myPassword : String, myHashedPassword : String) { // add objects (within a transaction) ... let a = MyRealmSwiftObject() @@ -69,7 +69,7 @@ func test1(realm : Realm, myUsername: String, myPassword : String, myHashedPassw // MyRealmSwiftObject2... let h = MyRealmSwiftObject2() - h.username = myUsername // GOOD (not sensitive) + h.harmless = myHarmless // GOOD (not sensitive) h.password = myPassword // BAD realm.add(h) } diff --git a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift index aaf2e3487f2..e7021f6e99a 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift +++ b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift @@ -41,7 +41,14 @@ func test1(passwordPlain : String, passwordHash : String) { func pad(_ data: String) -> String { return data } func aes_crypt(_ data: String) -> String { return data } -func test2(password : String, connection : NWConnection) { +struct MyStruct { + var mobileNumber: String + var mobileUrl: String + var mobilePlayer: String + var passwordFeatureEnabled: Bool +} + +func test2(password : String, license_key: String, ms: MyStruct, connection : NWConnection) { let str1 = password let str2 = password + " " let str3 = pad(password) @@ -55,4 +62,9 @@ func test2(password : String, connection : NWConnection) { connection.send(content: str4, completion: .idempotent) // GOOD (encrypted) connection.send(content: str5, completion: .idempotent) // GOOD (encrypted) connection.send(content: str6, completion: .idempotent) // GOOD (encrypted) + connection.send(content: license_key, completion: .idempotent) // BAD + connection.send(content: ms.mobileNumber, completion: .idempotent) // BAD + connection.send(content: ms.mobileUrl, completion: .idempotent) // GOOD (not sensitive) + connection.send(content: ms.mobilePlayer, completion: .idempotent) // GOOD (not sensitive) + connection.send(content: ms.passwordFeatureEnabled, completion: .idempotent) // GOOD (not sensitive) } diff --git a/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp b/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp index 6dd010036cf..d19479eae7d 100644 --- a/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp +++ b/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp @@ -9,17 +9,21 @@ const std::string_view codeql::programName = "autobuilder"; constexpr codeql::SwiftDiagnostic incompatibleOs{ - "incompatible-os", "Incompatible operating system for autobuild (expected macOS)", - "Change the action runner to a macOS one. Analysis on Linux might work, but requires setting " - "up a custom build command", + "incompatible-os", + "Incompatible operating system (expected macOS)", + "[Change the Actions runner][1] to run on macOS.\n" + "\n" + "You may be able to run analysis on Linux by setting up a [manual build command][2].\n" + "\n" + "[1]: " "https://docs.github.com/en/actions/using-workflows/" - "workflow-syntax-for-github-actions#jobsjob_idruns-on " - "https://docs.github.com/en/enterprise-server/code-security/code-scanning/" - "automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning " + "workflow-syntax-for-github-actions#jobsjob_idruns-on\n" + "[2]: " "https://docs.github.com/en/enterprise-server/code-security/code-scanning/" "automatically-scanning-your-code-for-vulnerabilities-and-errors/" "configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-" - "language"}; + "language", +}; static codeql::Logger& logger() { static codeql::Logger ret{"main"}; @@ -28,6 +32,6 @@ static codeql::Logger& logger() { int main() { DIAGNOSE_ERROR(incompatibleOs, - "CodeQL Swift analysis is currently only officially supported on macOS"); + "Currently, `autobuild` for Swift analysis is only supported on macOS"); return 1; } diff --git a/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h b/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h index d8c68136e2f..453fa70c13f 100644 --- a/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h +++ b/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h @@ -1,12 +1,13 @@ #include +#include "swift/logging/SwiftDiagnostics.h" namespace codeql { -constexpr std::string_view customizingBuildAction = "Set up a manual build command"; -constexpr std::string_view customizingBuildHelpLinks = +constexpr std::string_view customizingBuildAction = "Set up a manual build command."; +constexpr SwiftDiagnostic::HelpLinks customizingBuildHelpLinks{ "https://docs.github.com/en/enterprise-server/code-security/code-scanning/" "automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning " "https://docs.github.com/en/enterprise-server/code-security/code-scanning/" "automatically-scanning-your-code-for-vulnerabilities-and-errors/" "configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-" - "language"; + "language"}; } // namespace codeql diff --git a/swift/xcode-autobuilder/XcodeBuildRunner.cpp b/swift/xcode-autobuilder/XcodeBuildRunner.cpp index 163a639db00..b209caa3df9 100644 --- a/swift/xcode-autobuilder/XcodeBuildRunner.cpp +++ b/swift/xcode-autobuilder/XcodeBuildRunner.cpp @@ -10,7 +10,7 @@ constexpr codeql::SwiftDiagnostic buildCommandFailed{ "build-command-failed", "Detected build command failed", codeql::customizingBuildAction, - codeql::customizingBuildHelpLinks}; + codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildHelpLinks}; static codeql::Logger& logger() { static codeql::Logger ret{"build"}; diff --git a/swift/xcode-autobuilder/xcode-autobuilder.cpp b/swift/xcode-autobuilder/xcode-autobuilder.cpp index 5a00c885880..067c4d24139 100644 --- a/swift/xcode-autobuilder/xcode-autobuilder.cpp +++ b/swift/xcode-autobuilder/xcode-autobuilder.cpp @@ -14,15 +14,16 @@ const std::string_view codeql::programName = "autobuilder"; constexpr codeql::SwiftDiagnostic noProjectFound{ "no-project-found", "No Xcode project or workspace detected", codeql::customizingBuildAction, - codeql::customizingBuildHelpLinks}; + codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildHelpLinks}; constexpr codeql::SwiftDiagnostic noSwiftTarget{ "no-swift-target", "No Swift compilation target found", codeql::customizingBuildAction, - codeql::customizingBuildHelpLinks}; + codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildHelpLinks}; constexpr codeql::SwiftDiagnostic spmNotSupported{ "spm-not-supported", "Swift Package Manager build unsupported by autobuild", - codeql::customizingBuildAction, codeql::customizingBuildHelpLinks}; + codeql::customizingBuildAction, codeql::SwiftDiagnostic::Format::plaintext, + codeql::customizingBuildHelpLinks}; static codeql::Logger& logger() { static codeql::Logger ret{"main"};