Skip to content

Commit 0299b46

Browse files
authored
Merge pull request github#7677 from hvitved/ruby/constant-value
Ruby: Replace `getValueText` with `getConstantValue`
2 parents 82ad79f + cc712c2 commit 0299b46

37 files changed

+959
-456
lines changed

ruby/ql/lib/codeql/ruby/Concepts.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ module HTTP {
239239
string getUrlPattern() {
240240
exists(CfgNodes::ExprNodes::StringlikeLiteralCfgNode strNode |
241241
this.getUrlPatternArg().getALocalSource() = DataFlow::exprNode(strNode) and
242-
result = strNode.getExpr().getValueText()
242+
result = strNode.getExpr().getConstantValue().getStringOrSymbol()
243243
)
244244
}
245245

@@ -364,7 +364,7 @@ module HTTP {
364364
string getMimetype() {
365365
exists(CfgNodes::ExprNodes::StringlikeLiteralCfgNode strNode |
366366
this.getMimetypeOrContentTypeArg().getALocalSource() = DataFlow::exprNode(strNode) and
367-
result = strNode.getExpr().getValueText().splitAt(";", 0)
367+
result = strNode.getExpr().getConstantValue().getStringOrSymbol().splitAt(";", 0)
368368
)
369369
or
370370
not exists(this.getMimetypeOrContentTypeArg()) and

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Call extends Expr instanceof CallImpl {
4141
final Expr getKeywordArgument(string keyword) {
4242
exists(Pair p |
4343
p = this.getAnArgument() and
44-
p.getKey().(SymbolLiteral).getValueText() = keyword and
44+
p.getKey().getConstantValue().isSymbol(keyword) and
4545
result = p.getValue()
4646
)
4747
}

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

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,110 @@
11
private import codeql.ruby.AST
22
private import internal.AST
3+
private import internal.Constant
34
private import internal.Module
45
private import internal.Variable
56
private import internal.TreeSitter
67

8+
/** A constant value. */
9+
class ConstantValue extends TConstantValue {
10+
/** Gets a textual representation of this constant value. */
11+
final string toString() {
12+
result = this.getInt().toString()
13+
or
14+
result = this.getFloat().toString()
15+
or
16+
exists(int numerator, int denominator |
17+
this.isRational(numerator, denominator) and
18+
result = numerator + "/" + denominator
19+
)
20+
or
21+
exists(float real, float imaginary |
22+
this.isComplex(real, imaginary) and
23+
result = real + "+" + imaginary + "i"
24+
)
25+
or
26+
result = this.getString()
27+
or
28+
result = ":" + this.getSymbol()
29+
or
30+
result = this.getBoolean().toString()
31+
or
32+
this.isNil() and result = "nil"
33+
}
34+
35+
/** Gets the integer value, if this is an integer. */
36+
int getInt() { this = TInt(result) }
37+
38+
/** Holds if this is the integer value `i`. */
39+
predicate isInt(int i) { i = this.getInt() }
40+
41+
/** Gets the float value, if this is a float. */
42+
float getFloat() { this = TFloat(result) }
43+
44+
/** Holds if this is the float value `f`. */
45+
predicate isFloat(float f) { f = this.getFloat() }
46+
47+
/** Holds if this is the rational value `numerator / denominator`. */
48+
predicate isRational(int numerator, int denominator) { this = TRational(numerator, denominator) }
49+
50+
/** Holds if this is the complex value `real + imaginary * i`. */
51+
predicate isComplex(float real, float imaginary) { this = TComplex(real, imaginary) }
52+
53+
/** Gets the string value, if this is a string. */
54+
string getString() { this = TString(result) }
55+
56+
/** Holds if this is the string value `s`. */
57+
predicate isString(string s) { s = this.getString() }
58+
59+
/** Gets the symbol value (exluding the `:` prefix), if this is a symbol. */
60+
string getSymbol() { this = TSymbol(result) }
61+
62+
/** Holds if this is the symbol value `:s`. */
63+
predicate isSymbol(string s) { s = this.getSymbol() }
64+
65+
/** Gets the string or symbol value, if any. */
66+
string getStringOrSymbol() { result = [this.getString(), this.getSymbol()] }
67+
68+
/** Holds if this is the string value `s` or the symbol value `:s`. */
69+
predicate isStringOrSymbol(string s) { s = this.getStringOrSymbol() }
70+
71+
/** Gets the Boolean value, if this is a Boolean. */
72+
boolean getBoolean() { this = TBoolean(result) }
73+
74+
/** Holds if this is the Boolean value `b`. */
75+
predicate isBoolean(boolean b) { b = this.getBoolean() }
76+
77+
/** Holds if this is the `nil` value. */
78+
predicate isNil() { this = TNil() }
79+
}
80+
81+
/** Provides different sub classes of `ConstantValue`. */
82+
module ConstantValue {
83+
/** A constant integer value. */
84+
class ConstantIntegerValue extends ConstantValue, TInt { }
85+
86+
/** A constant float value. */
87+
class ConstantFloatValue extends ConstantValue, TFloat { }
88+
89+
/** A constant rational value. */
90+
class ConstantRationalValue extends ConstantValue, TRational { }
91+
92+
/** A constant complex value. */
93+
class ConstantComplexValue extends ConstantValue, TComplex { }
94+
95+
/** A constant string value. */
96+
class ConstantStringValue extends ConstantValue, TString { }
97+
98+
/** A constant symbol value. */
99+
class ConstantSymbolValue extends ConstantValue, TSymbol { }
100+
101+
/** A constant Boolean value. */
102+
class ConstantBooleanValue extends ConstantValue, TBoolean { }
103+
104+
/** A constant `nil` value. */
105+
class ConstantNilValue extends ConstantValue, TNil { }
106+
}
107+
7108
/** An access to a constant. */
8109
class ConstantAccess extends Expr, TConstantAccess {
9110
/** Gets the name of the constant being accessed. */
@@ -139,7 +240,7 @@ class ConstantReadAccess extends ConstantAccess {
139240
result = lookupConst(resolveConstantReadAccess(this.getScopeExpr()), this.getName())
140241
}
141242

142-
override string getValueText() { result = this.getValue().getValueText() }
243+
final override ConstantValue getConstantValue() { result = this.getValue().getConstantValue() }
143244

144245
final override string getAPrimaryQlClass() { result = "ConstantReadAccess" }
145246
}

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
private import codeql.ruby.AST
22
private import codeql.ruby.CFG
3+
private import codeql.ruby.ast.Constant
34
private import internal.AST
45
private import internal.Expr
56
private import internal.TreeSitter
@@ -10,9 +11,16 @@ private import internal.TreeSitter
1011
* This is the root QL class for all expressions.
1112
*/
1213
class Expr extends Stmt, TExpr {
13-
/** Gets the textual (constant) value of this expression, if any. */
14-
string getValueText() {
15-
forex(CfgNodes::ExprCfgNode n | n = this.getAControlFlowNode() | result = n.getValueText())
14+
/**
15+
* DEPRECATED: Use `getConstantValue` instead.
16+
*
17+
* Gets the textual (constant) value of this expression, if any.
18+
*/
19+
deprecated string getValueText() { result = this.getConstantValue().toString() }
20+
21+
/** Gets the constant value of this expression, if any. */
22+
ConstantValue getConstantValue() {
23+
forex(CfgNodes::ExprCfgNode n | n = this.getAControlFlowNode() | result = n.getConstantValue())
1624
}
1725
}
1826

@@ -456,10 +464,12 @@ class StringConcatenation extends Expr, TStringConcatenation {
456464
* ```
457465
*/
458466
final string getConcatenatedValueText() {
459-
forall(StringLiteral c | c = this.getString(_) | exists(c.getValueText())) and
467+
forall(StringLiteral c | c = this.getString(_) |
468+
exists(c.getConstantValue().getStringOrSymbol())
469+
) and
460470
result =
461471
concat(string valueText, int i |
462-
valueText = this.getString(i).getValueText()
472+
valueText = this.getString(i).getConstantValue().getStringOrSymbol()
463473
|
464474
valueText order by i
465475
)

0 commit comments

Comments
 (0)