CFG: Model nodes with simple flow

This commit is contained in:
Arthur Baars
2020-11-25 16:48:53 +01:00
parent 3807e1be38
commit 97d0220ffd
3 changed files with 362 additions and 2 deletions

View File

@@ -228,6 +228,14 @@ abstract private class LeafTree extends PreOrderTree, PostOrderTree {
/** Defines the CFG by dispatch on the various AST types. */
private module Trees {
private class AliasTree extends StandardPreOrderTree, Alias {
final override AstNode getChildNode(int i) {
i = 0 and result = this.getName()
or
i = 1 and result = this.getAlias()
}
}
private class ArgumentListTree extends StandardPostOrderTree, ArgumentList {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
@@ -246,6 +254,22 @@ private module Trees {
}
}
private class BareStringTree extends StandardPostOrderTree, BareString {
final override AstNode getChildNode(int i) {
result = this.getChild(i) and result instanceof Interpolation
}
}
private class BareSymbolTree extends StandardPostOrderTree, BareSymbol {
final override AstNode getChildNode(int i) {
result = this.getChild(i) and result instanceof Interpolation
}
}
private class BeginTree extends StandardPreOrderTree, Begin {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
private class BeginBlockTree extends StandardPreOrderTree, BeginBlock {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
@@ -260,7 +284,21 @@ private module Trees {
}
}
private class BlockParametersTree extends LeafTree, BlockParameters {
private class BlockTree extends StandardPreOrderTree, Block {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
override predicate isHidden() { any() }
}
private class BlockArgumentTree extends StandardPostOrderTree, BlockArgument {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class BlockParameterTree extends LeafTree, BlockParameter { }
private class BlockParametersTree extends StandardPreOrderTree, BlockParameters {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
override predicate isHidden() { any() }
}
@@ -314,10 +352,33 @@ private module Trees {
}
}
private class ChainedStringTree extends StandardPostOrderTree, ChainedString {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
override predicate isHidden() { any() }
}
private class CharacterTree extends LeafTree, Character { }
private class ClassTree extends StandardPreOrderTree, Class {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
private class ClassVariableTree extends LeafTree, ClassVariable { }
private class ComplexTree extends LeafTree, Complex { }
private class ConstantTree extends LeafTree, Constant { }
private class DestructuredLeftAssignmentTree extends StandardPostOrderTree,
DestructuredLeftAssignment {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
private class DestructuredParameterTree extends StandardPostOrderTree, DestructuredParameter {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
private class DoTree extends StandardPreOrderTree, Do {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
@@ -330,16 +391,50 @@ private module Trees {
override predicate isHidden() { any() }
}
private class ElementReferenceTree extends StandardPostOrderTree, ElementReference {
final override AstNode getChildNode(int i) {
i = 0 and result = this.getObject()
or
result = this.getChild(i - 1)
}
}
private class ElseTree extends StandardPreOrderTree, Else {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
override predicate isHidden() { any() }
}
private class EmptyStatementTree extends LeafTree, EmptyStatement { }
private class EndBlockTree extends StandardPreOrderTree, EndBlock {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
private class EnsureTree extends StandardPreOrderTree, Ensure {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
override predicate isHidden() { any() }
}
private class EscapeSequenceTree extends LeafTree, EscapeSequence { }
private class ExceptionVariableTree extends StandardPostOrderTree, ExceptionVariable {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
override predicate isHidden() { any() }
}
private class ExceptionsTree extends StandardPostOrderTree, Exceptions {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
override predicate isHidden() { any() }
}
private class FalseTree extends LeafTree, False { }
private class FloatTree extends LeafTree, Float { }
/**
* Control flow of a for-in loop
*
@@ -431,6 +526,18 @@ private module Trees {
}
}
private class GlobalVariableTree extends LeafTree, GlobalVariable { }
private class HashTree extends StandardPostOrderTree, Hash {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
private class HashSplatArgumentTree extends StandardPostOrderTree, HashSplatArgument {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class HashSplatParameterTree extends LeafTree, HashSplatParameter { }
private class HeredocBeginningTree extends StandardPreOrderTree, HeredocBeginning {
final override AstNode getChildNode(int i) {
i = 0 and
@@ -452,6 +559,16 @@ private module Trees {
}
}
private class HeredocBodyTree extends StandardPostOrderTree, HeredocBody {
final override AstNode getChildNode(int i) {
result = this.getChild(i) and result instanceof Interpolation
}
}
private class HeredocContentTree extends LeafTree, HeredocContent { }
private class HeredocEndTree extends LeafTree, HeredocEnd { }
private class IdentifierTree extends LeafTree, Identifier { }
private class IfElsifTree extends PreOrderTree, IfElsifAstNode {
@@ -491,8 +608,40 @@ private module Trees {
override predicate isHidden() { any() }
}
private class InstanceVariableTree extends LeafTree, InstanceVariable { }
private class IntegerTree extends LeafTree, Integer { }
private class InterpolationTree extends StandardPostOrderTree, Interpolation {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class KeywordParameterTree extends StandardPostOrderTree, KeywordParameter {
final override AstNode getChildNode(int i) { result = this.getValue() and i = 0 }
}
private class LambdaTree extends StandardPreOrderTree, Lambda {
final override AstNode getChildNode(int i) {
result = this.getParameters() and i = 0
or
result = this.getBody() and i = 1
}
override predicate isHidden() { any() }
}
private class LambdaParametersTree extends StandardPreOrderTree, LambdaParameters {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
override predicate isHidden() { any() }
}
private class LeftAssignmentListTree extends StandardPostOrderTree, LeftAssignmentList {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
override predicate isHidden() { any() }
}
class LogicalAndTree extends PostOrderTree, LogicalAndAstNode {
final override predicate propagatesAbnormal(AstNode child) { child in [left, right] }
@@ -564,6 +713,12 @@ private module Trees {
}
}
private class MethodParametersTree extends StandardPreOrderTree, MethodParameters {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
override predicate isHidden() { any() }
}
private class ModuleTree extends StandardPreOrderTree, Module {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
@@ -572,6 +727,8 @@ private module Trees {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class NilTree extends LeafTree, Nil { }
private class OperatorAssignmentTree extends StandardPostOrderTree, OperatorAssignment {
final override AstNode getChildNode(int i) {
result = this.getLeft() and i = 0
@@ -580,6 +737,18 @@ private module Trees {
}
}
private class OptionalParameterTree extends StandardPostOrderTree, OptionalParameter {
final override AstNode getChildNode(int i) { result = this.getValue() and i = 0 }
}
private class PairTree extends StandardPostOrderTree, Pair {
final override AstNode getChildNode(int i) {
result = this.getKey() and i = 0
or
result = this.getValue() and i = 1
}
}
private class ParenthesizedStatementsTree extends StandardPostOrderTree, ParenthesizedStatements {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
@@ -594,10 +763,32 @@ private module Trees {
override predicate isHidden() { any() }
}
private class RangeTree extends StandardPostOrderTree, Range {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
private class RationalTree extends LeafTree, Rational { }
private class RedoTree extends StandardPostOrderTree, Redo {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class RegexTree extends StandardPostOrderTree, Regex {
final override AstNode getChildNode(int i) {
result = this.getChild(i) and result instanceof Interpolation
}
}
private class RescueTree extends StandardPreOrderTree, Rescue {
final override AstNode getChildNode(int i) {
result = this.getExceptions() and i = 0
or
result = this.getVariable() and i = 1
or
result = this.getBody() and i = 2
}
}
private class RescueModifierTree extends PreOrderTree, RescueModifier {
final override predicate propagatesAbnormal(AstNode child) { child = this.getHandler() }
@@ -619,10 +810,36 @@ private module Trees {
}
}
private class RestAssignmentTree extends StandardPostOrderTree, RestAssignment {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class RetryTree extends StandardPreOrderTree, Retry {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class ReturnTree extends StandardPostOrderTree, Return {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class RightAssignmentListTree extends StandardPostOrderTree, RightAssignmentList {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
override predicate isHidden() { any() }
}
private class ScopeResolutionTree extends StandardPostOrderTree, ScopeResolution {
final override AstNode getChildNode(int i) {
result = this.getScope() and i = 0
or
result = this.getName() and i = 1
}
}
private class SelfTree extends LeafTree, Self { }
private class SetterTree extends LeafTree, Setter { }
private class SingletonClassTree extends StandardPreOrderTree, SingletonClass {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
@@ -635,7 +852,47 @@ private module Trees {
override predicate isHidden() { any() }
}
private class StringTree extends LeafTree, String { }
private class SplatArgumentTree extends StandardPostOrderTree, SplatArgument {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class SplatParameterTree extends StandardPostOrderTree, SplatArgument {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class StringTree extends StandardPostOrderTree, String {
final override AstNode getChildNode(int i) {
result = this.getChild(i) and result instanceof Interpolation
}
}
private class StringArrayTree extends StandardPostOrderTree, StringArray {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
private class StringContentTree extends LeafTree, StringContent { }
private class SubshellTree extends StandardPostOrderTree, Subshell {
final override AstNode getChildNode(int i) {
result = this.getChild(i) and result instanceof Interpolation
}
}
private class SuperTree extends LeafTree, Super { }
private class SuperclassTree extends StandardPostOrderTree, Superclass {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
private class SymbolTree extends StandardPostOrderTree, Symbol {
final override AstNode getChildNode(int i) {
result = this.getChild(i) and result instanceof Interpolation
}
}
private class SymbolArrayTree extends StandardPostOrderTree, SymbolArray {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
private class ThenTree extends StandardPreOrderTree, Then {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
@@ -643,12 +900,18 @@ private module Trees {
override predicate isHidden() { any() }
}
private class TrueTree extends LeafTree, True { }
private class UnaryTree extends StandardPostOrderTree, Unary {
UnaryTree() { not this instanceof LogicalNotAstNode }
final override AstNode getChildNode(int i) { result = this.getOperand() and i = 0 }
}
private class UndefTree extends StandardPreOrderTree, Undef {
final override AstNode getChildNode(int i) { result = this.getChild(i) }
}
private class WhenTree extends PreOrderTree, When {
final override predicate propagatesAbnormal(AstNode child) { child = this.getPattern(_) }
@@ -718,6 +981,10 @@ private module Trees {
}
}
private class YieldTree extends StandardPreOrderTree, Yield {
final override AstNode getChildNode(int i) { result = this.getChild() and i = 0 }
}
cached
private module Cached {
private predicate isAbnormalExitType(SuccessorType t) {

View File

@@ -1,4 +1,41 @@
nodes
| cfg.rb:1:1:22:2 | enter top-level |
| cfg.rb:1:1:22:2 | exit top-level |
| cfg.rb:1:1:22:2 | exit top-level (normal) |
| cfg.rb:3:1:3:13 | Alias |
| cfg.rb:3:7:3:9 | foo |
| cfg.rb:3:11:3:13 | bar |
| cfg.rb:5:1:5:1 | b |
| cfg.rb:5:1:5:6 | Assignment |
| cfg.rb:5:5:5:6 | 42 |
| cfg.rb:7:1:7:21 | SymbolArray |
| cfg.rb:7:4:7:12 | BareSymbol |
| cfg.rb:7:7:7:12 | Interpolation |
| cfg.rb:7:10:7:10 | b |
| cfg.rb:7:14:7:20 | BareSymbol |
| cfg.rb:9:1:9:21 | StringArray |
| cfg.rb:9:4:9:12 | BareString |
| cfg.rb:9:7:9:12 | Interpolation |
| cfg.rb:9:10:9:10 | b |
| cfg.rb:9:14:9:20 | BareString |
| cfg.rb:12:1:14:3 | Begin |
| cfg.rb:13:3:13:6 | puts |
| cfg.rb:13:3:13:8 | MethodCall |
| cfg.rb:13:8:13:8 | 4 |
| cfg.rb:16:1:18:1 | BeginBlock |
| cfg.rb:16:1:18:1 | enter BEGIN block |
| cfg.rb:16:1:18:1 | exit BEGIN block |
| cfg.rb:16:1:18:1 | exit BEGIN block (normal) |
| cfg.rb:17:3:17:6 | puts |
| cfg.rb:17:3:17:14 | MethodCall |
| cfg.rb:17:8:17:14 | String |
| cfg.rb:20:1:22:1 | EndBlock |
| cfg.rb:20:1:22:1 | enter END block |
| cfg.rb:20:1:22:1 | exit END block |
| cfg.rb:20:1:22:1 | exit END block (normal) |
| cfg.rb:21:3:21:6 | puts |
| cfg.rb:21:3:21:14 | MethodCall |
| cfg.rb:21:8:21:14 | String |
| exit.rb:1:1:6:3 | enter m1 |
| exit.rb:1:1:6:3 | exit m1 |
| exit.rb:1:1:6:3 | exit m1 (abnormal) |
@@ -171,6 +208,40 @@ nodes
| raise.rb:5:3:5:15 | MethodCall |
| raise.rb:5:8:5:15 | String |
edges
| cfg.rb:1:1:22:2 | enter top-level | cfg.rb:3:1:3:13 | Alias | semmle.label | successor |
| cfg.rb:1:1:22:2 | exit top-level (normal) | cfg.rb:1:1:22:2 | exit top-level | semmle.label | successor |
| cfg.rb:3:1:3:13 | Alias | cfg.rb:3:7:3:9 | foo | semmle.label | successor |
| cfg.rb:3:7:3:9 | foo | cfg.rb:3:11:3:13 | bar | semmle.label | successor |
| cfg.rb:3:11:3:13 | bar | cfg.rb:5:5:5:6 | 42 | semmle.label | successor |
| cfg.rb:5:1:5:1 | b | cfg.rb:5:1:5:6 | Assignment | semmle.label | successor |
| cfg.rb:5:1:5:6 | Assignment | cfg.rb:7:10:7:10 | b | semmle.label | successor |
| cfg.rb:5:5:5:6 | 42 | cfg.rb:5:1:5:1 | b | semmle.label | successor |
| cfg.rb:7:1:7:21 | SymbolArray | cfg.rb:9:10:9:10 | b | semmle.label | successor |
| cfg.rb:7:4:7:12 | BareSymbol | cfg.rb:7:14:7:20 | BareSymbol | semmle.label | successor |
| cfg.rb:7:7:7:12 | Interpolation | cfg.rb:7:4:7:12 | BareSymbol | semmle.label | successor |
| cfg.rb:7:10:7:10 | b | cfg.rb:7:7:7:12 | Interpolation | semmle.label | successor |
| cfg.rb:7:14:7:20 | BareSymbol | cfg.rb:7:1:7:21 | SymbolArray | semmle.label | successor |
| cfg.rb:9:1:9:21 | StringArray | cfg.rb:12:1:14:3 | Begin | semmle.label | successor |
| cfg.rb:9:4:9:12 | BareString | cfg.rb:9:14:9:20 | BareString | semmle.label | successor |
| cfg.rb:9:7:9:12 | Interpolation | cfg.rb:9:4:9:12 | BareString | semmle.label | successor |
| cfg.rb:9:10:9:10 | b | cfg.rb:9:7:9:12 | Interpolation | semmle.label | successor |
| cfg.rb:9:14:9:20 | BareString | cfg.rb:9:1:9:21 | StringArray | semmle.label | successor |
| cfg.rb:12:1:14:3 | Begin | cfg.rb:13:8:13:8 | 4 | semmle.label | successor |
| cfg.rb:13:3:13:6 | puts | cfg.rb:13:3:13:8 | MethodCall | semmle.label | successor |
| cfg.rb:13:3:13:8 | MethodCall | cfg.rb:1:1:22:2 | exit top-level (normal) | semmle.label | successor |
| cfg.rb:13:8:13:8 | 4 | cfg.rb:13:3:13:6 | puts | semmle.label | successor |
| cfg.rb:16:1:18:1 | BeginBlock | cfg.rb:17:8:17:14 | String | semmle.label | successor |
| cfg.rb:16:1:18:1 | enter BEGIN block | cfg.rb:16:1:18:1 | BeginBlock | semmle.label | successor |
| cfg.rb:16:1:18:1 | exit BEGIN block (normal) | cfg.rb:16:1:18:1 | exit BEGIN block | semmle.label | successor |
| cfg.rb:17:3:17:6 | puts | cfg.rb:17:3:17:14 | MethodCall | semmle.label | successor |
| cfg.rb:17:3:17:14 | MethodCall | cfg.rb:16:1:18:1 | exit BEGIN block (normal) | semmle.label | successor |
| cfg.rb:17:8:17:14 | String | cfg.rb:17:3:17:6 | puts | semmle.label | successor |
| cfg.rb:20:1:22:1 | EndBlock | cfg.rb:21:8:21:14 | String | semmle.label | successor |
| cfg.rb:20:1:22:1 | enter END block | cfg.rb:20:1:22:1 | EndBlock | semmle.label | successor |
| cfg.rb:20:1:22:1 | exit END block (normal) | cfg.rb:20:1:22:1 | exit END block | semmle.label | successor |
| cfg.rb:21:3:21:6 | puts | cfg.rb:21:3:21:14 | MethodCall | semmle.label | successor |
| cfg.rb:21:3:21:14 | MethodCall | cfg.rb:20:1:22:1 | exit END block (normal) | semmle.label | successor |
| cfg.rb:21:8:21:14 | String | cfg.rb:21:3:21:6 | puts | semmle.label | successor |
| exit.rb:1:1:6:3 | enter m1 | exit.rb:2:3:4:5 | If | semmle.label | successor |
| exit.rb:1:1:6:3 | exit m1 (abnormal) | exit.rb:1:1:6:3 | exit m1 | semmle.label | successor |
| exit.rb:1:1:6:3 | exit m1 (normal) | exit.rb:1:1:6:3 | exit m1 | semmle.label | successor |

View File

@@ -0,0 +1,22 @@
def bar; end
alias foo bar
b = 42
%I(one#{ b } another) # bare symbol
%W(one#{ b } another) # bare string
begin
puts 4
end
BEGIN {
puts "hello"
}
END {
puts "world"
}