Skip to content

Commit 2f3e526

Browse files
committed
Add class wrappers around newtype in Cfg.qll
1 parent 5d69e14 commit 2f3e526

File tree

4 files changed

+219
-148
lines changed

4 files changed

+219
-148
lines changed

ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll

Lines changed: 18 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,58 +10,22 @@ private import internal.ControlFlowGraphImpl as CfgImpl
1010
private import internal.Splitting
1111

1212
/** An entry node for a given scope. */
13-
class EntryNode extends CfgNode, CfgImpl::TEntryNode {
13+
class EntryNode extends CfgNode, CfgImpl::EntryNode {
1414
override string getAPrimaryQlClass() { result = "EntryNode" }
1515

16-
private CfgScope scope;
17-
18-
EntryNode() { this = CfgImpl::TEntryNode(scope) }
19-
2016
final override EntryBasicBlock getBasicBlock() { result = super.getBasicBlock() }
21-
22-
final override Location getLocation() { result = scope.getLocation() }
23-
24-
final override string toString() { result = "enter " + scope }
2517
}
2618

2719
/** An exit node for a given scope, annotated with the type of exit. */
28-
class AnnotatedExitNode extends CfgNode, CfgImpl::TAnnotatedExitNode {
20+
class AnnotatedExitNode extends CfgNode, CfgImpl::AnnotatedExitNode {
2921
override string getAPrimaryQlClass() { result = "AnnotatedExitNode" }
3022

31-
private CfgScope scope;
32-
private boolean normal;
33-
34-
AnnotatedExitNode() { this = CfgImpl::TAnnotatedExitNode(scope, normal) }
35-
36-
/** Holds if this node represent a normal exit. */
37-
final predicate isNormal() { normal = true }
38-
3923
final override AnnotatedExitBasicBlock getBasicBlock() { result = super.getBasicBlock() }
40-
41-
final override Location getLocation() { result = scope.getLocation() }
42-
43-
final override string toString() {
44-
exists(string s |
45-
normal = true and s = "normal"
46-
or
47-
normal = false and s = "abnormal"
48-
|
49-
result = "exit " + scope + " (" + s + ")"
50-
)
51-
}
5224
}
5325

5426
/** An exit node for a given scope. */
55-
class ExitNode extends CfgNode, CfgImpl::TExitNode {
27+
class ExitNode extends CfgNode, CfgImpl::ExitNode {
5628
override string getAPrimaryQlClass() { result = "ExitNode" }
57-
58-
private CfgScope scope;
59-
60-
ExitNode() { this = CfgImpl::TExitNode(scope) }
61-
62-
final override Location getLocation() { result = scope.getLocation() }
63-
64-
final override string toString() { result = "exit " + scope }
6529
}
6630

6731
/**
@@ -71,42 +35,16 @@ class ExitNode extends CfgNode, CfgImpl::TExitNode {
7135
* (dead) code or not important for control flow, and multiple when there are different
7236
* splits for the AST node.
7337
*/
74-
class AstCfgNode extends CfgNode, CfgImpl::TElementNode {
38+
class AstCfgNode extends CfgNode, CfgImpl::AstCfgNode {
7539
/** Gets the name of the primary QL class for this node. */
7640
override string getAPrimaryQlClass() { result = "AstCfgNode" }
77-
78-
private CfgImpl::Splits splits;
79-
AstNode e;
80-
81-
AstCfgNode() { this = CfgImpl::TElementNode(_, e, splits) }
82-
83-
final override AstNode getNode() { result = e }
84-
85-
override Location getLocation() { result = e.getLocation() }
86-
87-
final override string toString() {
88-
exists(string s | s = e.toString() |
89-
result = "[" + this.getSplitsString() + "] " + s
90-
or
91-
not exists(this.getSplitsString()) and result = s
92-
)
93-
}
94-
95-
/** Gets a comma-separated list of strings for each split in this node, if any. */
96-
final string getSplitsString() {
97-
result = splits.toString() and
98-
result != ""
99-
}
100-
101-
/** Gets a split for this control flow node, if any. */
102-
final Split getASplit() { result = splits.getASplit() }
10341
}
10442

10543
/** A control-flow node that wraps an AST expression. */
10644
class ExprCfgNode extends AstCfgNode {
10745
override string getAPrimaryQlClass() { result = "ExprCfgNode" }
10846

109-
override Expr e;
47+
Expr e;
11048

11149
ExprCfgNode() { e = this.getNode() }
11250

@@ -146,7 +84,7 @@ class StringComponentCfgNode extends AstCfgNode {
14684
class RegExpComponentCfgNode extends StringComponentCfgNode {
14785
override string getAPrimaryQlClass() { result = "RegExpComponentCfgNode" }
14886

149-
RegExpComponentCfgNode() { e instanceof RegExpComponent }
87+
RegExpComponentCfgNode() { this.getNode() instanceof RegExpComponent }
15088
}
15189

15290
private AstNode desugar(AstNode n) {
@@ -440,9 +378,11 @@ module ExprNodes {
440378

441379
/** A control-flow node that wraps an `InClause` AST expression. */
442380
class InClauseCfgNode extends AstCfgNode {
443-
override string getAPrimaryQlClass() { result = "InClauseCfgNode" }
381+
private InClauseChildMapping e;
382+
383+
InClauseCfgNode() { e = this.getNode() }
444384

445-
override InClauseChildMapping e;
385+
override string getAPrimaryQlClass() { result = "InClauseCfgNode" }
446386

447387
/** Gets the pattern in this `in`-clause. */
448388
final AstCfgNode getPattern() { e.hasCfgChild(e.getPattern(), this, result) }
@@ -488,9 +428,11 @@ module ExprNodes {
488428

489429
/** A control-flow node that wraps a `WhenClause` AST expression. */
490430
class WhenClauseCfgNode extends AstCfgNode {
491-
override string getAPrimaryQlClass() { result = "WhenClauseCfgNode" }
431+
private WhenClauseChildMapping e;
492432

493-
override WhenClauseChildMapping e;
433+
WhenClauseCfgNode() { e = this.getNode() }
434+
435+
override string getAPrimaryQlClass() { result = "WhenClauseCfgNode" }
494436

495437
/** Gets the body of this `when`-clause. */
496438
final ExprCfgNode getBody() {
@@ -507,9 +449,11 @@ module ExprNodes {
507449

508450
/** A control-flow node that wraps a `CasePattern`. */
509451
class CasePatternCfgNode extends AstCfgNode {
510-
override string getAPrimaryQlClass() { result = "CasePatternCfgNode" }
452+
CasePattern e;
511453

512-
override CasePattern e;
454+
CasePatternCfgNode() { e = this.getNode() }
455+
456+
override string getAPrimaryQlClass() { result = "CasePatternCfgNode" }
513457
}
514458

515459
private class ArrayPatternChildMapping extends NonExprChildMapping, ArrayPattern {

ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,33 +33,15 @@ class CfgScope extends Scope instanceof CfgImpl::CfgScopeImpl {
3333
*
3434
* Only nodes that can be reached from an entry point are included in the CFG.
3535
*/
36-
class CfgNode extends CfgImpl::TCfgNode {
36+
class CfgNode extends CfgImpl::Node {
3737
/** Gets the name of the primary QL class for this node. */
3838
string getAPrimaryQlClass() { none() }
3939

40-
/** Gets a textual representation of this control flow node. */
41-
string toString() { none() }
42-
43-
/** Gets the AST node that this node corresponds to, if any. */
44-
AstNode getNode() { none() }
45-
46-
/** Gets the location of this control flow node. */
47-
Location getLocation() { none() }
48-
4940
/** Gets the file of this control flow node. */
5041
final File getFile() { result = this.getLocation().getFile() }
5142

52-
/** Holds if this control flow node has conditional successors. */
53-
final predicate isCondition() { exists(this.getASuccessor(any(ConditionalSuccessor bs))) }
54-
55-
/** Gets the scope of this node. */
56-
final CfgScope getScope() { result = CfgImpl::getNodeCfgScope(this) }
57-
58-
/** Gets the basic block that this control flow node belongs to. */
59-
BasicBlock getBasicBlock() { result.getANode() = this }
60-
6143
/** Gets a successor node of a given type, if any. */
62-
final CfgNode getASuccessor(SuccessorType t) { result = CfgImpl::getASuccessor(this, t) }
44+
final CfgNode getASuccessor(SuccessorType t) { result = super.getASuccessor(t) }
6345

6446
/** Gets an immediate successor, if any. */
6547
final CfgNode getASuccessor() { result = this.getASuccessor(_) }
@@ -70,11 +52,8 @@ class CfgNode extends CfgImpl::TCfgNode {
7052
/** Gets an immediate predecessor, if any. */
7153
final CfgNode getAPredecessor() { result = this.getAPredecessor(_) }
7254

73-
/** Holds if this node has more than one predecessor. */
74-
final predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
75-
76-
/** Holds if this node has more than one successor. */
77-
final predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
55+
/** Gets the basic block that this control flow node belongs to. */
56+
BasicBlock getBasicBlock() { result.getANode() = this }
7857
}
7958

8059
/** The type of a control flow successor. */

ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,17 @@ private module CfgInput implements CfgShared::InputSig<Location> {
5959
t instanceof Cfg::SuccessorTypes::NormalSuccessor
6060
}
6161

62+
predicate successorTypeIsCondition(SuccessorType t) {
63+
t instanceof Cfg::SuccessorTypes::ConditionalSuccessor
64+
}
65+
6266
predicate isAbnormalExitType(SuccessorType t) {
6367
t instanceof Cfg::SuccessorTypes::RaiseSuccessor or
6468
t instanceof Cfg::SuccessorTypes::ExitSuccessor
6569
}
6670
}
6771

68-
private module Shared = CfgShared::Make<Location, CfgInput>;
69-
70-
import Shared
71-
72-
module TestOutput = Shared::TestOutput<CfgNode>;
73-
74-
module Consistency = Shared::Consistency<CfgNode>;
72+
import CfgShared::Make<Location, CfgInput>
7573

7674
abstract class CfgScopeImpl extends AstNode {
7775
abstract predicate entry(AstNode first);

0 commit comments

Comments
 (0)