Skip to content

Commit 7d7e9ba

Browse files
committed
Ruby: add CasePattern classes to CfgNodes
1 parent e9a01f9 commit 7d7e9ba

File tree

2 files changed

+142
-10
lines changed

2 files changed

+142
-10
lines changed

ruby/ql/lib/codeql/ruby/ast/Pattern.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ private class TPattern =
9999
class CasePattern extends AstNode, TPattern {
100100
CasePattern() {
101101
casePattern(toGenerated(this)) or
102-
this = any(HashPattern p).getValue(_)
102+
synthChild(any(HashPattern p), _, this)
103103
}
104104
}
105105

@@ -270,7 +270,7 @@ class HashPattern extends CasePattern, THashPattern {
270270
StringlikeLiteral getKey(int n) { toGenerated(result) = this.keyValuePair(n).getKey() }
271271

272272
/** Gets the value of the `n`th pair. */
273-
AstNode getValue(int n) {
273+
CasePattern getValue(int n) {
274274
toGenerated(result) = this.keyValuePair(n).getValue() or
275275
synthChild(this, n, result)
276276
}
@@ -387,6 +387,7 @@ class ParenthesizedPattern extends CasePattern, TParenthesizedPattern {
387387

388388
ParenthesizedPattern() { this = TParenthesizedPattern(g) }
389389

390+
/** Gets the underlying pattern. */
390391
final CasePattern getPattern() { toGenerated(result) = g.getChild() }
391392

392393
final override string getAPrimaryQlClass() { result = "ParenthesizedPattern" }

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

Lines changed: 139 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,16 @@ class ExitNode extends CfgNode, TExitNode {
6565
*/
6666
class AstCfgNode extends CfgNode, TElementNode {
6767
private Splits splits;
68-
private AstNode n;
68+
AstNode e;
6969

70-
AstCfgNode() { this = TElementNode(_, n, splits) }
70+
AstCfgNode() { this = TElementNode(_, e, splits) }
7171

72-
final override AstNode getNode() { result = n }
72+
final override AstNode getNode() { result = e }
7373

74-
override Location getLocation() { result = n.getLocation() }
74+
override Location getLocation() { result = e.getLocation() }
7575

7676
final override string toString() {
77-
exists(string s | s = n.toString() |
77+
exists(string s | s = e.toString() |
7878
result = "[" + this.getSplitsString() + "] " + s
7979
or
8080
not exists(this.getSplitsString()) and result = s
@@ -93,7 +93,7 @@ class AstCfgNode extends CfgNode, TElementNode {
9393

9494
/** A control-flow node that wraps an AST expression. */
9595
class ExprCfgNode extends AstCfgNode {
96-
Expr e;
96+
override Expr e;
9797

9898
ExprCfgNode() { e = this.getNode() }
9999

@@ -410,7 +410,7 @@ module ExprNodes {
410410

411411
/** A control-flow node that wraps an `InClause` AST expression. */
412412
class InClauseCfgNode extends AstCfgNode {
413-
private InClauseChildMapping e;
413+
override InClauseChildMapping e;
414414

415415
/**
416416
* Gets the pattern in this `in`-clause.
@@ -430,12 +430,136 @@ module ExprNodes {
430430

431431
/** A control-flow node that wraps a `WhenClause` AST expression. */
432432
class WhenClauseCfgNode extends AstCfgNode {
433-
private WhenClauseChildMapping e;
433+
override WhenClauseChildMapping e;
434434

435435
/** Gets the body of this `when`-clause. */
436436
final ExprCfgNode getBody() { e.hasCfgChild(e.getBody(), this, result) }
437437
}
438438

439+
/** A control-flow node that wraps a `CasePattern`. */
440+
class CasePatternCfgNode extends AstCfgNode {
441+
override CasePattern e;
442+
}
443+
444+
private class ArrayPatternChildMapping extends NonExprChildMapping, ArrayPattern {
445+
override predicate relevantChild(AstNode e) {
446+
e = this.getPrefixElement(_) or
447+
e = this.getSuffixElement(_) or
448+
e = this.getRestVariableAccess()
449+
}
450+
}
451+
452+
/** A control-flow node that wraps a `ArrayPattern` node. */
453+
class ArrayPatternCfgNode extends CasePatternCfgNode {
454+
override ArrayPatternChildMapping e;
455+
456+
/** Gets the `n`th element of this list pattern's prefix. */
457+
final CasePatternCfgNode getPrefixElement(int n) {
458+
e.hasCfgChild(e.getPrefixElement(n), this, result)
459+
}
460+
461+
/** Gets the `n`th element of this list pattern's suffix. */
462+
final CasePatternCfgNode getSuffixElement(int n) {
463+
e.hasCfgChild(e.getSuffixElement(n), this, result)
464+
}
465+
466+
/** Gets the variable of the rest token, if any. */
467+
final VariableWriteAccessCfgNode getRestVariableAccess() {
468+
e.hasCfgChild(e.getRestVariableAccess(), this, result)
469+
}
470+
}
471+
472+
private class FindPatternChildMapping extends NonExprChildMapping, FindPattern {
473+
override predicate relevantChild(AstNode e) {
474+
e = this.getElement(_) or
475+
e = this.getPrefixVariableAccess() or
476+
e = this.getSuffixVariableAccess()
477+
}
478+
}
479+
480+
/** A control-flow node that wraps a `FindPattern` node. */
481+
class FindPatternCfgNode extends CasePatternCfgNode {
482+
override FindPatternChildMapping e;
483+
484+
/** Gets the `n`th element of this find pattern. */
485+
final CasePatternCfgNode getElement(int n) { e.hasCfgChild(e.getElement(n), this, result) }
486+
487+
/** Gets the variable for the prefix of this list pattern, if any. */
488+
final VariableWriteAccessCfgNode getPrefixVariableAccess() {
489+
e.hasCfgChild(e.getPrefixVariableAccess(), this, result)
490+
}
491+
492+
/** Gets the variable for the suffix of this list pattern, if any. */
493+
final VariableWriteAccessCfgNode getSuffixVariableAccess() {
494+
e.hasCfgChild(e.getSuffixVariableAccess(), this, result)
495+
}
496+
}
497+
498+
private class HashPatternChildMapping extends NonExprChildMapping, HashPattern {
499+
override predicate relevantChild(AstNode e) {
500+
e = this.getValue(_) or
501+
e = this.getRestVariableAccess()
502+
}
503+
}
504+
505+
/** A control-flow node that wraps a `HashPattern` node. */
506+
class HashPatternCfgNode extends CasePatternCfgNode {
507+
override HashPatternChildMapping e;
508+
509+
/** Gets the value of the `n`th pair. */
510+
final CasePatternCfgNode getValue(int n) { e.hasCfgChild(e.getValue(n), this, result) }
511+
512+
/** Gets the variable of the keyword rest token, if any. */
513+
final VariableWriteAccessCfgNode getRestVariableAccess() {
514+
e.hasCfgChild(e.getRestVariableAccess(), this, result)
515+
}
516+
}
517+
518+
private class AlternativePatternChildMapping extends NonExprChildMapping, AlternativePattern {
519+
override predicate relevantChild(AstNode e) { e = this.getAnAlternative() }
520+
}
521+
522+
/** A control-flow node that wraps a `AlternativePattern` node. */
523+
class AlternativePatternCfgNode extends CasePatternCfgNode {
524+
override AlternativePatternChildMapping e;
525+
526+
/** Gets the `n`th alternative. */
527+
final CasePatternCfgNode getAlternative(int n) {
528+
e.hasCfgChild(e.getAlternative(n), this, result)
529+
}
530+
}
531+
532+
private class AsPatternChildMapping extends NonExprChildMapping, AsPattern {
533+
override predicate relevantChild(AstNode e) {
534+
e = this.getPattern() or e = this.getVariableAccess()
535+
}
536+
}
537+
538+
/** A control-flow node that wraps a `AsPattern` node. */
539+
class AsPatternCfgNode extends CasePatternCfgNode {
540+
override AsPatternChildMapping e;
541+
542+
/** Gets the underlying pattern. */
543+
final CasePatternCfgNode getPattern() { e.hasCfgChild(e.getPattern(), this, result) }
544+
545+
/** Gets the variable access for this pattern. */
546+
final VariableWriteAccessCfgNode getVariableAccess() {
547+
e.hasCfgChild(e.getVariableAccess(), this, result)
548+
}
549+
}
550+
551+
private class ParenthesizedPatternChildMapping extends NonExprChildMapping, ParenthesizedPattern {
552+
override predicate relevantChild(AstNode e) { e = this.getPattern() }
553+
}
554+
555+
/** A control-flow node that wraps a `ParenthesizedPattern` node. */
556+
class ParenthesizedPatternCfgNode extends CasePatternCfgNode {
557+
override ParenthesizedPatternChildMapping e;
558+
559+
/** Gets the underlying pattern. */
560+
final CasePatternCfgNode getPattern() { e.hasCfgChild(e.getPattern(), this, result) }
561+
}
562+
439563
private class ConditionalExprChildMapping extends ExprChildMapping, ConditionalExpr {
440564
override predicate relevantChild(AstNode n) { n = [this.getCondition(), this.getBranch(_)] }
441565
}
@@ -533,6 +657,13 @@ module ExprNodes {
533657
final override VariableReadAccess getExpr() { result = ExprCfgNode.super.getExpr() }
534658
}
535659

660+
/** A control-flow node that wraps a `VariableWriteAccess` AST expression. */
661+
class VariableWriteAccessCfgNode extends ExprCfgNode {
662+
override VariableWriteAccess e;
663+
664+
final override VariableWriteAccess getExpr() { result = ExprCfgNode.super.getExpr() }
665+
}
666+
536667
/** A control-flow node that wraps a `InstanceVariableWriteAccess` AST expression. */
537668
class InstanceVariableWriteAccessCfgNode extends ExprCfgNode {
538669
override InstanceVariableWriteAccess e;

0 commit comments

Comments
 (0)