Skip to content

Commit f6681f3

Browse files
authored
Merge pull request #8399 from github/nickrolfe/simple_symbol_constant_value
Ruby: implement getComponent(n) for simple and hash-key symbols
2 parents f53df25 + 94ce578 commit f6681f3

File tree

10 files changed

+1035
-30
lines changed

10 files changed

+1035
-30
lines changed

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

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -226,24 +226,61 @@ class StringComponent extends AstNode, TStringComponent {
226226
* ```
227227
*/
228228
class StringTextComponent extends StringComponent, TStringTextComponentNonRegexp {
229+
final override string getAPrimaryQlClass() { result = "StringTextComponent" }
230+
231+
/** Gets the text of this component as it appears in the source code. */
232+
string getRawText() { none() }
233+
}
234+
235+
private class StringTextComponentStringOrHeredocContent extends StringTextComponent,
236+
TStringTextComponentNonRegexpStringOrHeredocContent {
229237
private Ruby::Token g;
230238

231-
StringTextComponent() { this = TStringTextComponentNonRegexp(g) }
239+
StringTextComponentStringOrHeredocContent() {
240+
this = TStringTextComponentNonRegexpStringOrHeredocContent(g)
241+
}
232242

233243
final override string toString() { result = this.getRawText() }
234244

235245
final override ConstantValue::ConstantStringValue getConstantValue() {
236246
result.isString(this.getUnescapedText())
237247
}
238248

239-
final override string getAPrimaryQlClass() { result = "StringTextComponent" }
240-
241-
/** Gets the text of this component as it appears in the source code. */
242-
final string getRawText() { result = g.getValue() }
249+
final override string getRawText() { result = g.getValue() }
243250

244251
final private string getUnescapedText() { result = unescapeTextComponent(this.getRawText()) }
245252
}
246253

254+
private class StringTextComponentSimpleSymbol extends StringTextComponent,
255+
TStringTextComponentNonRegexpSimpleSymbol {
256+
private Ruby::SimpleSymbol g;
257+
258+
StringTextComponentSimpleSymbol() { this = TStringTextComponentNonRegexpSimpleSymbol(g) }
259+
260+
final override string toString() { result = getSimpleSymbolValue(g) }
261+
262+
final override ConstantValue::ConstantStringValue getConstantValue() {
263+
result.isString(getSimpleSymbolValue(g))
264+
}
265+
266+
final override string getRawText() { result = getSimpleSymbolValue(g) }
267+
}
268+
269+
private class StringTextComponentHashKeySymbol extends StringTextComponent,
270+
TStringTextComponentNonRegexpHashKeySymbol {
271+
private Ruby::HashKeySymbol g;
272+
273+
StringTextComponentHashKeySymbol() { this = TStringTextComponentNonRegexpHashKeySymbol(g) }
274+
275+
final override string toString() { result = g.getValue() }
276+
277+
final override ConstantValue::ConstantStringValue getConstantValue() {
278+
result.isString(g.getValue())
279+
}
280+
281+
final override string getRawText() { result = g.getValue() }
282+
}
283+
247284
/**
248285
* An escape sequence component of a string or string-like literal.
249286
*/
@@ -575,18 +612,6 @@ class SymbolLiteral extends StringlikeLiteral, TSymbolLiteral {
575612
}
576613
}
577614

578-
private class SimpleSymbolLiteral extends SymbolLiteral, TSimpleSymbolLiteral {
579-
private Ruby::SimpleSymbol g;
580-
581-
SimpleSymbolLiteral() { this = TSimpleSymbolLiteral(g) }
582-
583-
final override ConstantValue::ConstantSymbolValue getConstantValue() {
584-
result.isSymbol(getSimpleSymbolValue(g))
585-
}
586-
587-
final override string toString() { result = g.getValue() }
588-
}
589-
590615
/**
591616
* A subshell literal.
592617
*

ruby/ql/lib/codeql/ruby/ast/internal/AST.qll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,12 @@ private module Cached {
284284
TStringInterpolationComponentRegexp(Ruby::Interpolation g) {
285285
g.getParent() instanceof Ruby::Regex
286286
} or
287-
TStringTextComponentNonRegexp(Ruby::Token g) {
287+
TStringTextComponentNonRegexpStringOrHeredocContent(Ruby::Token g) {
288288
(g instanceof Ruby::StringContent or g instanceof Ruby::HeredocContent) and
289289
not g.getParent() instanceof Ruby::Regex
290290
} or
291+
TStringTextComponentNonRegexpSimpleSymbol(Ruby::SimpleSymbol g) or
292+
TStringTextComponentNonRegexpHashKeySymbol(Ruby::HashKeySymbol g) or
291293
TStringTextComponentRegexp(Ruby::Token g) {
292294
(g instanceof Ruby::StringContent or g instanceof Ruby::HeredocContent) and
293295
g.getParent() instanceof Ruby::Regex
@@ -511,7 +513,9 @@ private module Cached {
511513
n = TStringEscapeSequenceComponentRegexp(result) or
512514
n = TStringInterpolationComponentNonRegexp(result) or
513515
n = TStringInterpolationComponentRegexp(result) or
514-
n = TStringTextComponentNonRegexp(result) or
516+
n = TStringTextComponentNonRegexpStringOrHeredocContent(result) or
517+
n = TStringTextComponentNonRegexpSimpleSymbol(result) or
518+
n = TStringTextComponentNonRegexpHashKeySymbol(result) or
515519
n = TStringTextComponentRegexp(result) or
516520
n = TSubExprReal(result) or
517521
n = TSubshellLiteral(result) or
@@ -702,6 +706,10 @@ class TIntegerLiteral = TIntegerLiteralReal or TIntegerLiteralSynth;
702706

703707
class TBooleanLiteral = TTrueLiteral or TFalseLiteral;
704708

709+
class TStringTextComponentNonRegexp =
710+
TStringTextComponentNonRegexpStringOrHeredocContent or
711+
TStringTextComponentNonRegexpSimpleSymbol or TStringTextComponentNonRegexpHashKeySymbol;
712+
705713
class TStringTextComponent = TStringTextComponentNonRegexp or TStringTextComponentRegexp;
706714

707715
class TStringEscapeSequenceComponent =

ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,23 @@ private class RequiredFileLiteralConstantValue extends RequiredConstantValue {
126126
}
127127
}
128128

129-
private class RequiredStringTextComponentConstantValue extends RequiredConstantValue {
129+
private class RequiredStringTextComponentNonRegexpStringOrHeredocContentConstantValue extends RequiredConstantValue {
130130
override predicate requiredString(string s) {
131131
s =
132-
unescapeTextComponent(any(Ruby::Token t | exists(TStringTextComponentNonRegexp(t))).getValue())
132+
unescapeTextComponent(any(Ruby::Token t |
133+
exists(TStringTextComponentNonRegexpStringOrHeredocContent(t))
134+
).getValue())
133135
}
134136
}
135137

138+
private class RequiredStringTextComponentNonRegexpSimpleSymbolConstantValue extends RequiredConstantValue {
139+
override predicate requiredString(string s) { s = getSimpleSymbolValue(_) }
140+
}
141+
142+
private class RequiredStringTextComponentNonRegexpHashKeySymbolConstantValue extends RequiredConstantValue {
143+
override predicate requiredString(string s) { s = any(Ruby::HashKeySymbol h).getValue() }
144+
}
145+
136146
private class RequiredStringEscapeSequenceComponentConstantValue extends RequiredConstantValue {
137147
override predicate requiredString(string s) {
138148
s =
@@ -272,6 +282,8 @@ private class SimpleSymbolLiteral extends SymbolLiteral, TSimpleSymbolLiteral {
272282
}
273283

274284
final override string toString() { result = g.getValue() }
285+
286+
final override StringComponent getComponent(int n) { n = 0 and toGenerated(result) = g }
275287
}
276288

277289
class ComplexSymbolLiteral extends SymbolLiteral, TComplexSymbolLiteral { }
@@ -306,6 +318,8 @@ private class HashKeySymbolLiteral extends SymbolLiteral, THashKeySymbolLiteral
306318
}
307319

308320
final override string toString() { result = ":" + g.getValue() }
321+
322+
final override StringComponent getComponent(int n) { n = 0 and toGenerated(result) = g }
309323
}
310324

311325
private class RequiredCharacterConstantValue extends RequiredConstantValue {

0 commit comments

Comments
 (0)