Distinguish regex components from strings

Create a set of classes for components of regex literals,
separate from those of string literals. This allows us to special-case
components of free-spacing regexes (ones with the /x flag) to not have a
`getValueText()`.

This in turn is useful because our regex parser can't handle free-spacing
regexes, so excluding them ensures that we don't generate erroneous
ReDoS alerts.
This commit is contained in:
Harry Maclean
2022-01-18 15:02:13 +13:00
parent ac9cac78bc
commit 4f7f92490a
7 changed files with 193 additions and 78 deletions

View File

@@ -277,7 +277,9 @@ class StringComponent extends AstNode, TStringComponent {
class StringTextComponent extends StringComponent, TStringTextComponent {
private Ruby::Token g;
StringTextComponent() { this = TStringTextComponent(g) }
StringTextComponent() {
this = TStringTextComponent(g) and not g.getParent() instanceof Ruby::Regex
}
final override string toString() { result = g.getValue() }
@@ -292,7 +294,9 @@ class StringTextComponent extends StringComponent, TStringTextComponent {
class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequenceComponent {
private Ruby::EscapeSequence g;
StringEscapeSequenceComponent() { this = TStringEscapeSequenceComponent(g) }
StringEscapeSequenceComponent() {
this = TStringEscapeSequenceComponent(g) and not g.getParent() instanceof Ruby::Regex
}
final override string toString() { result = g.getValue() }
@@ -308,7 +312,9 @@ class StringInterpolationComponent extends StringComponent, StmtSequence,
TStringInterpolationComponent {
private Ruby::Interpolation g;
StringInterpolationComponent() { this = TStringInterpolationComponent(g) }
StringInterpolationComponent() {
this = TStringInterpolationComponent(g) and not g.getParent() instanceof Ruby::Regex
}
final override string toString() { result = "#{...}" }
@@ -319,6 +325,82 @@ class StringInterpolationComponent extends StringComponent, StmtSequence,
final override string getAPrimaryQlClass() { result = "StringInterpolationComponent" }
}
/**
* The base class for a component of a regular expression literal.
*/
class RegExpComponent extends AstNode, TStringComponent {
private RegExpLiteral parent;
RegExpComponent() { toGenerated(this).getParent() = toGenerated(parent) }
string getValueText() { none() }
}
/**
* A component of a regex literal that is simply text.
*
* For example, the following regex literals all contain `RegExpTextComponent`
* components whose `getValueText()` returns `"foo"`:
*
* ```rb
* 'foo'
* "#{ bar() }foo"
* "foo#{ bar() } baz"
* ```
*/
class RegExpTextComponent extends RegExpComponent, TStringTextComponent {
private Ruby::Token g;
RegExpTextComponent() { this = TStringTextComponent(g) and g.getParent() instanceof Ruby::Regex }
final override string toString() { result = g.getValue() }
// Exclude components that are children of a free-spacing regex.
// We do this because `ParseRegExp.qll` cannot handle free-spacing regexes.
final override string getValueText() {
not this.getParent().(RegExpLiteral).hasFreeSpacingFlag() and result = g.getValue()
}
final override string getAPrimaryQlClass() { result = "RegExpTextComponent" }
}
/**
* An escape sequence component of a regex literal.
*/
class RegExpEscapeSequenceComponent extends RegExpComponent, TStringEscapeSequenceComponent {
private Ruby::EscapeSequence g;
RegExpEscapeSequenceComponent() { this = TStringEscapeSequenceComponent(g) }
final override string toString() { result = g.getValue() }
// Exclude components that are children of a free-spacing regex.
// We do this because `ParseRegExp.qll` cannot handle free-spacing regexes.
final override string getValueText() {
not this.getParent().(RegExpLiteral).hasFreeSpacingFlag() and result = g.getValue()
}
final override string getAPrimaryQlClass() { result = "RegExpEscapeSequenceComponent" }
}
/**
* An interpolation expression component of a regex literal.
*/
class RegExpInterpolationComponent extends RegExpComponent, StmtSequence,
TStringInterpolationComponent {
private Ruby::Interpolation g;
RegExpInterpolationComponent() { this = TStringInterpolationComponent(g) }
final override string toString() { result = "#{...}" }
final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
final override string getValueText() { none() }
final override string getAPrimaryQlClass() { result = "RegExpInterpolationComponent" }
}
/**
* A string, symbol, regexp, or subshell literal.
*/

View File

@@ -132,6 +132,13 @@ class StringComponentCfgNode extends AstCfgNode {
string getValueText() { result = this.getNode().(StringComponent).getValueText() }
}
/** A control-flow node that wraps a `RegExpComponent` AST expression. */
class RegExpComponentCfgNode extends AstCfgNode {
RegExpComponentCfgNode() { this.getNode() instanceof RegExpComponent }
string getValueText() { result = this.getNode().(RegExpComponent).getValueText() }
}
private AstNode desugar(AstNode n) {
result = n.getDesugared()
or
@@ -474,6 +481,15 @@ module ExprNodes {
final override string getValueText() { result = this.getLastStmt().getValueText() }
}
/** A control-flow node that wraps a `RegExpInterpolationComponent` AST expression. */
class RegExpInterpolationComponentCfgNode extends RegExpComponentCfgNode, StmtSequenceCfgNode {
RegExpInterpolationComponentCfgNode() { this.getNode() instanceof RegExpInterpolationComponent }
// If last statement in the interpolation is a constant or local variable read,
// attempt to look up its definition and return the definition's `getValueText()`.
final override string getValueText() { result = this.getLastStmt().getValueText() }
}
private class StringlikeLiteralChildMapping extends ExprChildMapping, StringlikeLiteral {
override predicate relevantChild(AstNode n) { n = this.getComponent(_) }
}
@@ -510,11 +526,27 @@ module ExprNodes {
final override StringLiteral getExpr() { result = super.getExpr() }
}
private class RegExpLiteralChildMapping extends ExprChildMapping, RegExpLiteral {
override predicate relevantChild(AstNode n) { n = this.getComponent(_) }
}
/** A control-flow node that wraps a `RegExpLiteral` AST expression. */
class RegExpLiteralCfgNode extends ExprCfgNode {
override RegExpLiteral e;
override RegExpLiteralChildMapping e;
RegExpComponentCfgNode getComponent(int n) { e.hasCfgChild(e.getComponent(n), this, result) }
final override RegExpLiteral getExpr() { result = super.getExpr() }
language[monotonicAggregates]
override string getValueText() {
result =
concat(RegExpComponentCfgNode c, int i |
c = this.getComponent(i)
|
c.getValueText() order by i
)
}
}
/** A control-flow node that wraps a `ComparisonOperation` AST expression. */

View File

@@ -1351,7 +1351,13 @@ module Trees {
}
private class StringComponentTree extends LeafTree, StringComponent {
StringComponentTree() { not this instanceof StringInterpolationComponent }
StringComponentTree() {
// Interpolations contain `StmtSequence`s, so they shouldn't be treated as leaf nodes.
not this instanceof StringInterpolationComponent and
// In the interests of brevity we treat regexes as string literals when constructing the CFG.
// Thus we must exclude regex interpolations here too.
not this instanceof RegExpInterpolationComponent
}
}
private class ToplevelTree extends BodyStmtTree, Toplevel {

View File

@@ -946,7 +946,7 @@ control/cases.rb:
# 92| 0: [RegExpCharacterRange] 0-9
# 92| 0: [RegExpConstant, RegExpNormalChar] 0
# 92| 1: [RegExpConstant, RegExpNormalChar] 9
# 92| getComponent: [StringTextComponent] .*abc[0-9]
# 92| getComponent: [RegExpTextComponent] .*abc[0-9]
# 93| getBranch: [InClause] in ... then ...
# 93| getPattern: [RangeLiteral] _ .. _
# 93| getBegin: [IntegerLiteral] 5
@@ -1761,13 +1761,13 @@ literals/literals.rb:
# 137| 0: [RegExpConstant, RegExpNormalChar] f
# 137| 1: [RegExpConstant, RegExpNormalChar] o
# 137| 2: [RegExpConstant, RegExpNormalChar] o
# 137| getComponent: [StringTextComponent] foo
# 137| getComponent: [RegExpTextComponent] foo
# 138| getStmt: [RegExpLiteral] /foo/
# 138| getParsed: [RegExpSequence] foo
# 138| 0: [RegExpConstant, RegExpNormalChar] f
# 138| 1: [RegExpConstant, RegExpNormalChar] o
# 138| 2: [RegExpConstant, RegExpNormalChar] o
# 138| getComponent: [StringTextComponent] foo
# 138| getComponent: [RegExpTextComponent] foo
# 139| getStmt: [RegExpLiteral] /foo+\sbar\S/
# 139| getParsed: [RegExpSequence] foo+\sbar\S
# 139| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1779,10 +1779,10 @@ literals/literals.rb:
# 139| 5: [RegExpConstant, RegExpNormalChar] a
# 139| 6: [RegExpConstant, RegExpNormalChar] r
# 139| 7: [RegExpCharacterClassEscape] \S
# 139| getComponent: [StringTextComponent] foo+
# 139| getComponent: [StringEscapeSequenceComponent] \s
# 139| getComponent: [StringTextComponent] bar
# 139| getComponent: [StringEscapeSequenceComponent] \S
# 139| getComponent: [RegExpTextComponent] foo+
# 139| getComponent: [RegExpEscapeSequenceComponent] \s
# 139| getComponent: [RegExpTextComponent] bar
# 139| getComponent: [RegExpEscapeSequenceComponent] \S
# 140| getStmt: [RegExpLiteral] /foo#{...}bar#{...}#{...}/
# 140| getParsed: [RegExpSequence] foo2barbarbar
# 140| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1798,35 +1798,31 @@ literals/literals.rb:
# 140| 10: [RegExpConstant, RegExpNormalChar] b
# 140| 11: [RegExpConstant, RegExpNormalChar] a
# 140| 12: [RegExpConstant, RegExpNormalChar] r
# 140| getComponent: [StringTextComponent] foo
# 140| getComponent: [StringInterpolationComponent] #{...}
# 140| getComponent: [RegExpTextComponent] foo
# 140| getComponent: [RegExpInterpolationComponent] #{...}
# 140| getStmt: [AddExpr] ... + ...
# 140| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 140| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 140| getComponent: [StringTextComponent] bar
# 140| getComponent: [StringInterpolationComponent] #{...}
# 140| getComponent: [RegExpTextComponent] bar
# 140| getComponent: [RegExpInterpolationComponent] #{...}
# 140| getStmt: [LocalVariableAccess] bar
# 140| getComponent: [StringInterpolationComponent] #{...}
# 140| getComponent: [RegExpInterpolationComponent] #{...}
# 140| getStmt: [ConstantReadAccess] BAR
# 141| getStmt: [RegExpLiteral] /foo/
# 141| getParsed: [RegExpSequence] foo
# 141| 0: [RegExpConstant, RegExpNormalChar] f
# 141| 1: [RegExpConstant, RegExpNormalChar] o
# 141| 2: [RegExpConstant, RegExpNormalChar] o
# 141| getComponent: [StringTextComponent] foo
# 141| getComponent: [RegExpTextComponent] foo
# 142| getStmt: [RegExpLiteral] //
# 143| getStmt: [RegExpLiteral] /foo/
# 143| getParsed: [RegExpSequence] foo
# 143| 0: [RegExpConstant, RegExpNormalChar] f
# 143| 1: [RegExpConstant, RegExpNormalChar] o
# 143| 2: [RegExpConstant, RegExpNormalChar] o
# 143| getComponent: [StringTextComponent] foo
# 143| getComponent: [RegExpTextComponent] foo
# 144| getStmt: [RegExpLiteral] /foo/
# 144| getParsed: [RegExpSequence] foo
# 144| 0: [RegExpConstant, RegExpNormalChar] f
# 144| 1: [RegExpConstant, RegExpNormalChar] o
# 144| 2: [RegExpConstant, RegExpNormalChar] o
# 144| getComponent: [StringTextComponent] foo
# 144| getComponent: [RegExpTextComponent] foo
# 145| getStmt: [RegExpLiteral] /foo+\sbar\S/
# 145| getParsed: [RegExpSequence] foo+\sbar\S
# 145| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1838,10 +1834,10 @@ literals/literals.rb:
# 145| 5: [RegExpConstant, RegExpNormalChar] a
# 145| 6: [RegExpConstant, RegExpNormalChar] r
# 145| 7: [RegExpCharacterClassEscape] \S
# 145| getComponent: [StringTextComponent] foo+
# 145| getComponent: [StringEscapeSequenceComponent] \s
# 145| getComponent: [StringTextComponent] bar
# 145| getComponent: [StringEscapeSequenceComponent] \S
# 145| getComponent: [RegExpTextComponent] foo+
# 145| getComponent: [RegExpEscapeSequenceComponent] \s
# 145| getComponent: [RegExpTextComponent] bar
# 145| getComponent: [RegExpEscapeSequenceComponent] \S
# 146| getStmt: [RegExpLiteral] /foo#{...}bar#{...}#{...}/
# 146| getParsed: [RegExpSequence] foo2barbarbar
# 146| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1857,22 +1853,18 @@ literals/literals.rb:
# 146| 10: [RegExpConstant, RegExpNormalChar] b
# 146| 11: [RegExpConstant, RegExpNormalChar] a
# 146| 12: [RegExpConstant, RegExpNormalChar] r
# 146| getComponent: [StringTextComponent] foo
# 146| getComponent: [StringInterpolationComponent] #{...}
# 146| getComponent: [RegExpTextComponent] foo
# 146| getComponent: [RegExpInterpolationComponent] #{...}
# 146| getStmt: [AddExpr] ... + ...
# 146| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 146| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 146| getComponent: [StringTextComponent] bar
# 146| getComponent: [StringInterpolationComponent] #{...}
# 146| getComponent: [RegExpTextComponent] bar
# 146| getComponent: [RegExpInterpolationComponent] #{...}
# 146| getStmt: [LocalVariableAccess] bar
# 146| getComponent: [StringInterpolationComponent] #{...}
# 146| getComponent: [RegExpInterpolationComponent] #{...}
# 146| getStmt: [ConstantReadAccess] BAR
# 147| getStmt: [RegExpLiteral] /foo/
# 147| getParsed: [RegExpSequence] foo
# 147| 0: [RegExpConstant, RegExpNormalChar] f
# 147| 1: [RegExpConstant, RegExpNormalChar] o
# 147| 2: [RegExpConstant, RegExpNormalChar] o
# 147| getComponent: [StringTextComponent] foo
# 147| getComponent: [RegExpTextComponent] foo
# 150| getStmt: [StringLiteral] "abcdefghijklmnopqrstuvwxyzabcdef"
# 150| getComponent: [StringTextComponent] abcdefghijklmnopqrstuvwxyzabcdef
# 151| getStmt: [StringLiteral] "foobarfoobarfoobarfoobarfooba..."
@@ -2399,7 +2391,7 @@ operations/operations.rb:
# 65| 2: [RegExpConstant, RegExpNormalChar] o
# 65| 3: [RegExpStar] .*
# 65| 0: [RegExpDot] .
# 65| getComponent: [StringTextComponent] foo.*
# 65| getComponent: [RegExpTextComponent] foo.*
# 66| getStmt: [NoRegExpMatchExpr] ... !~ ...
# 66| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] handle
# 66| getAnOperand/getArgument/getRightOperand: [RegExpLiteral] /.*bar/
@@ -2409,7 +2401,7 @@ operations/operations.rb:
# 66| 1: [RegExpConstant, RegExpNormalChar] b
# 66| 2: [RegExpConstant, RegExpNormalChar] a
# 66| 3: [RegExpConstant, RegExpNormalChar] r
# 66| getComponent: [StringTextComponent] .*bar
# 66| getComponent: [RegExpTextComponent] .*bar
# 69| getStmt: [AssignAddExpr] ... += ...
# 69| getAnOperand/getLeftOperand: [LocalVariableAccess] x
# 69| getAnOperand/getRightOperand: [IntegerLiteral] 128

View File

@@ -552,7 +552,6 @@
| literals/literals.rb:140:12:140:12 | 1 | 1 |
| literals/literals.rb:140:20:140:22 | bar | bar |
| literals/literals.rb:140:26:140:28 | BAR | bar |
| literals/literals.rb:141:1:141:8 | /foo/ | foo |
| literals/literals.rb:142:1:142:4 | // | |
| literals/literals.rb:143:1:143:7 | /foo/ | foo |
| literals/literals.rb:144:1:144:8 | /foo/ | foo |
@@ -563,7 +562,6 @@
| literals/literals.rb:146:14:146:14 | 1 | 1 |
| literals/literals.rb:146:22:146:24 | bar | bar |
| literals/literals.rb:146:28:146:30 | BAR | bar |
| literals/literals.rb:147:1:147:10 | /foo/ | foo |
| literals/literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals/literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
| literals/literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |

View File

@@ -198,7 +198,7 @@ allLiterals
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | foo2barbarbar |
| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | foo |
| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | <none> |
| literals.rb:142:1:142:4 | // | RegExpLiteral | |
| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | foo |
| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | foo |
@@ -206,7 +206,7 @@ allLiterals
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | foo2barbarbar |
| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | foo |
| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | <none> |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | foobarfoobarfoobarfoobarfoobarfoo |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
@@ -310,13 +310,13 @@ stringlikeLiterals
| literals.rb:138:1:138:6 | /foo/ | foo |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
| literals.rb:141:1:141:8 | /foo/ | foo |
| literals.rb:141:1:141:8 | /foo/ | <none> |
| literals.rb:142:1:142:4 | // | |
| literals.rb:143:1:143:7 | /foo/ | foo |
| literals.rb:144:1:144:8 | /foo/ | foo |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
| literals.rb:147:1:147:10 | /foo/ | foo |
| literals.rb:147:1:147:10 | /foo/ | <none> |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
@@ -387,13 +387,20 @@ regExpLiterals
| literals.rb:138:1:138:6 | /foo/ | foo | i |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar | |
| literals.rb:141:1:141:8 | /foo/ | foo | oxm |
| literals.rb:141:1:141:8 | /foo/ | <none> | oxm |
| literals.rb:142:1:142:4 | // | | |
| literals.rb:143:1:143:7 | /foo/ | foo | |
| literals.rb:144:1:144:8 | /foo/ | foo | i |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar | |
| literals.rb:147:1:147:10 | /foo/ | foo | mxo |
| literals.rb:147:1:147:10 | /foo/ | <none> | mxo |
regExpInterpolations
| literals.rb:140:5:140:14 | #{...} | 0 | literals.rb:140:8:140:12 | ... + ... | AddExpr |
| literals.rb:140:18:140:23 | #{...} | 0 | literals.rb:140:20:140:22 | bar | LocalVariableAccess |
| literals.rb:140:24:140:29 | #{...} | 0 | literals.rb:140:26:140:28 | BAR | ConstantReadAccess |
| literals.rb:146:7:146:16 | #{...} | 0 | literals.rb:146:10:146:14 | ... + ... | AddExpr |
| literals.rb:146:20:146:25 | #{...} | 0 | literals.rb:146:22:146:24 | bar | LocalVariableAccess |
| literals.rb:146:26:146:31 | #{...} | 0 | literals.rb:146:28:146:30 | BAR | ConstantReadAccess |
symbolLiterals
| literals.rb:84:1:84:3 | :"" | |
| literals.rb:85:1:85:6 | :hello | hello |
@@ -540,30 +547,30 @@ stringComponents
| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 5 | literals.rb:132:26:132:31 | #{...} | StringInterpolationComponent |
| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:133:4:133:9 | du -d | StringTextComponent |
| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:133:10:133:19 | #{...} | StringInterpolationComponent |
| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | 0 | literals.rb:137:2:137:4 | foo | StringTextComponent |
| literals.rb:138:1:138:6 | /foo/ | RegExpLiteral | 0 | literals.rb:138:2:138:4 | foo | StringTextComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:139:2:139:5 | foo+ | StringTextComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:139:6:139:7 | \\s | StringEscapeSequenceComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:139:8:139:10 | bar | StringTextComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:139:11:139:12 | \\S | StringEscapeSequenceComponent |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:140:2:140:4 | foo | StringTextComponent |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:140:5:140:14 | #{...} | StringInterpolationComponent |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:140:15:140:17 | bar | StringTextComponent |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:140:18:140:23 | #{...} | StringInterpolationComponent |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:140:24:140:29 | #{...} | StringInterpolationComponent |
| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | 0 | literals.rb:141:2:141:4 | foo | StringTextComponent |
| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | 0 | literals.rb:143:4:143:6 | foo | StringTextComponent |
| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | 0 | literals.rb:144:4:144:6 | foo | StringTextComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:145:4:145:7 | foo+ | StringTextComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:145:8:145:9 | \\s | StringEscapeSequenceComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:145:10:145:12 | bar | StringTextComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:145:13:145:14 | \\S | StringEscapeSequenceComponent |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:146:4:146:6 | foo | StringTextComponent |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:146:7:146:16 | #{...} | StringInterpolationComponent |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:146:17:146:19 | bar | StringTextComponent |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:146:20:146:25 | #{...} | StringInterpolationComponent |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:146:26:146:31 | #{...} | StringInterpolationComponent |
| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | 0 | literals.rb:147:4:147:6 | foo | StringTextComponent |
| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | 0 | literals.rb:137:2:137:4 | foo | RegExpTextComponent |
| literals.rb:138:1:138:6 | /foo/ | RegExpLiteral | 0 | literals.rb:138:2:138:4 | foo | RegExpTextComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:139:2:139:5 | foo+ | RegExpTextComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:139:6:139:7 | \\s | RegExpEscapeSequenceComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:139:8:139:10 | bar | RegExpTextComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:139:11:139:12 | \\S | RegExpEscapeSequenceComponent |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:140:2:140:4 | foo | RegExpTextComponent |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:140:5:140:14 | #{...} | RegExpInterpolationComponent |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:140:15:140:17 | bar | RegExpTextComponent |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:140:18:140:23 | #{...} | RegExpInterpolationComponent |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:140:24:140:29 | #{...} | RegExpInterpolationComponent |
| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | 0 | literals.rb:141:2:141:4 | foo | RegExpTextComponent |
| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | 0 | literals.rb:143:4:143:6 | foo | RegExpTextComponent |
| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | 0 | literals.rb:144:4:144:6 | foo | RegExpTextComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:145:4:145:7 | foo+ | RegExpTextComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:145:8:145:9 | \\s | RegExpEscapeSequenceComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:145:10:145:12 | bar | RegExpTextComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:145:13:145:14 | \\S | RegExpEscapeSequenceComponent |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:146:4:146:6 | foo | RegExpTextComponent |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:146:7:146:16 | #{...} | RegExpInterpolationComponent |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:146:17:146:19 | bar | RegExpTextComponent |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:146:20:146:25 | #{...} | RegExpInterpolationComponent |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:146:26:146:31 | #{...} | RegExpInterpolationComponent |
| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | 0 | literals.rb:147:4:147:6 | foo | RegExpTextComponent |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | 0 | literals.rb:150:2:150:33 | abcdefghijklmnopqrstuvwxyzabcdef | StringTextComponent |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | 0 | literals.rb:151:2:151:34 | foobarfoobarfoobarfoobarfoobarfoo | StringTextComponent |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 0 | literals.rb:152:2:152:7 | foobar | StringTextComponent |
@@ -613,12 +620,6 @@ stringInterpolations
| literals.rb:132:19:132:24 | #{...} | 0 | literals.rb:132:21:132:23 | bar | LocalVariableAccess |
| literals.rb:132:26:132:31 | #{...} | 0 | literals.rb:132:28:132:30 | BAR | ConstantReadAccess |
| literals.rb:133:10:133:19 | #{...} | 0 | literals.rb:133:13:133:17 | ... - ... | SubExpr |
| literals.rb:140:5:140:14 | #{...} | 0 | literals.rb:140:8:140:12 | ... + ... | AddExpr |
| literals.rb:140:18:140:23 | #{...} | 0 | literals.rb:140:20:140:22 | bar | LocalVariableAccess |
| literals.rb:140:24:140:29 | #{...} | 0 | literals.rb:140:26:140:28 | BAR | ConstantReadAccess |
| literals.rb:146:7:146:16 | #{...} | 0 | literals.rb:146:10:146:14 | ... + ... | AddExpr |
| literals.rb:146:20:146:25 | #{...} | 0 | literals.rb:146:22:146:24 | bar | LocalVariableAccess |
| literals.rb:146:26:146:31 | #{...} | 0 | literals.rb:146:28:146:30 | BAR | ConstantReadAccess |
| literals.rb:158:14:158:22 | #{...} | 0 | literals.rb:158:17:158:20 | call to name | MethodCall |
| literals.rb:172:12:172:29 | #{...} | 0 | literals.rb:172:15:172:27 | call to interpolation | MethodCall |
| literals.rb:177:15:177:32 | #{...} | 0 | literals.rb:177:18:177:30 | call to interpolation | MethodCall |

View File

@@ -23,6 +23,10 @@ query predicate regExpLiterals(RegExpLiteral l, string valueText, string flags)
stringlikeLiterals(l, valueText) and flags = l.getFlagString()
}
query predicate regExpInterpolations(RegExpInterpolationComponent c, int i, Expr e, string eClass) {
e = c.getStmt(i) and eClass = e.getAPrimaryQlClass()
}
query predicate symbolLiterals(SymbolLiteral l, string valueText) {
stringlikeLiterals(l, valueText)
}