Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 85e1cda

Browse files
committed
Ruby: Distinguish symbols from strings in ConstantValue
1 parent aa9cfeb commit 85e1cda

27 files changed

Lines changed: 262 additions & 223 deletions

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().getConstantValue().getString()
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().getConstantValue().getString().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).getConstantValue().isString(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: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class ConstantValue extends TConstantValue {
2525
or
2626
result = this.getString()
2727
or
28+
result = ":" + this.getSymbol()
29+
or
2830
result = this.getBoolean().toString()
2931
or
3032
this.isNil() and result = "nil"
@@ -54,6 +56,18 @@ class ConstantValue extends TConstantValue {
5456
/** Holds if this is the string value `s`. */
5557
predicate isString(string s) { s = this.getString() }
5658

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+
5771
/** Gets the Boolean value, if this is a Boolean. */
5872
boolean getBoolean() { this = TBoolean(result) }
5973

@@ -81,6 +95,9 @@ module ConstantValue {
8195
/** A constant string value. */
8296
class ConstantStringValue extends ConstantValue, TString { }
8397

98+
/** A constant symbol value. */
99+
class ConstantSymbolValue extends ConstantValue, TSymbol { }
100+
84101
/** A constant Boolean value. */
85102
class ConstantBooleanValue extends ConstantValue, TBoolean { }
86103

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,10 +464,12 @@ class StringConcatenation extends Expr, TStringConcatenation {
464464
* ```
465465
*/
466466
final string getConcatenatedValueText() {
467-
forall(StringLiteral c | c = this.getString(_) | exists(c.getConstantValue().getString())) and
467+
forall(StringLiteral c | c = this.getString(_) |
468+
exists(c.getConstantValue().getStringOrSymbol())
469+
) and
468470
result =
469471
concat(string valueText, int i |
470-
valueText = this.getString(i).getConstantValue().getString()
472+
valueText = this.getString(i).getConstantValue().getStringOrSymbol()
471473
|
472474
valueText order by i
473475
)

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -761,17 +761,17 @@ class SymbolLiteral extends StringlikeLiteral, TSymbolLiteral {
761761
// Tree-sitter gives us value text including the colon, which we skip.
762762
private string getSimpleSymbolValue(Ruby::SimpleSymbol ss) { result = ss.getValue().suffix(1) }
763763

764-
private class RequiredStringConstantValue7 extends RequiredConstantValue {
765-
override predicate requiredString(string s) { s = getSimpleSymbolValue(_) }
764+
private class RequiredSymbolConstantValue extends RequiredConstantValue {
765+
override predicate requiredSymbol(string s) { s = getSimpleSymbolValue(_) }
766766
}
767767

768768
private class SimpleSymbolLiteral extends SymbolLiteral, TSimpleSymbolLiteral {
769769
private Ruby::SimpleSymbol g;
770770

771771
SimpleSymbolLiteral() { this = TSimpleSymbolLiteral(g) }
772772

773-
final override ConstantValue::ConstantStringValue getConstantValue() {
774-
result.isString(getSimpleSymbolValue(g))
773+
final override ConstantValue::ConstantSymbolValue getConstantValue() {
774+
result.isSymbol(getSimpleSymbolValue(g))
775775
}
776776

777777
final override string toString() { result = g.getValue() }
@@ -795,17 +795,17 @@ private class BareSymbolLiteral extends ComplexSymbolLiteral, TBareSymbolLiteral
795795
final override StringComponent getComponent(int i) { toGenerated(result) = g.getChild(i) }
796796
}
797797

798-
private class RequiredStringConstantValue8 extends RequiredConstantValue {
799-
override predicate requiredString(string s) { s = any(Ruby::HashKeySymbol h).getValue() }
798+
private class RequiredSymbolConstantValue2 extends RequiredConstantValue {
799+
override predicate requiredSymbol(string s) { s = any(Ruby::HashKeySymbol h).getValue() }
800800
}
801801

802802
private class HashKeySymbolLiteral extends SymbolLiteral, THashKeySymbolLiteral {
803803
private Ruby::HashKeySymbol g;
804804

805805
HashKeySymbolLiteral() { this = THashKeySymbolLiteral(g) }
806806

807-
final override ConstantValue::ConstantStringValue getConstantValue() {
808-
result.isString(g.getValue())
807+
final override ConstantValue::ConstantSymbolValue getConstantValue() {
808+
result.isSymbol(g.getValue())
809809
}
810810

811811
final override string toString() { result = ":" + g.getValue() }
@@ -829,7 +829,7 @@ class SubshellLiteral extends StringlikeLiteral, TSubshellLiteral {
829829
final override StringComponent getComponent(int i) { toGenerated(result) = g.getChild(i) }
830830
}
831831

832-
private class RequiredStringConstantValue9 extends RequiredConstantValue {
832+
private class RequiredStringConstantValue7 extends RequiredConstantValue {
833833
override predicate requiredString(string s) { s = any(Ruby::Character c).getValue() }
834834
}
835835

@@ -1131,7 +1131,7 @@ private string getMethodName(MethodName::Token t) {
11311131
result = t.(Ruby::Setter).getName().getValue() + "="
11321132
}
11331133

1134-
private class RequiredStringConstantValue10 extends RequiredConstantValue {
1134+
private class RequiredStringConstantValue8 extends RequiredConstantValue {
11351135
override predicate requiredString(string s) { s = getMethodName(_) }
11361136
}
11371137

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ private class MethodModifier extends MethodCall {
5353
predicate modifiesMethod(Namespace n, string name) {
5454
this = n.getAStmt() and
5555
[
56-
this.getMethodArgument().(StringlikeLiteral).getConstantValue().getString(),
56+
this.getMethodArgument().getConstantValue().getStringOrSymbol(),
5757
this.getMethodArgument().(MethodBase).getName()
5858
] = name
5959
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,9 @@ class HashPattern extends CasePattern, THashPattern {
271271

272272
/** Gets the value for a given key name. */
273273
CasePattern getValueByKey(string key) {
274-
exists(int i | this.getKey(i).getConstantValue().isString(key) and result = this.getValue(i))
274+
exists(int i |
275+
this.getKey(i).getConstantValue().isStringOrSymbol(key) and result = this.getValue(i)
276+
)
275277
}
276278

277279
/**

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ newtype TConstantValue =
99
any(RequiredConstantValue x).requiredComplex(real, imaginary)
1010
} or
1111
TString(string s) { any(RequiredConstantValue x).requiredString(s) } or
12+
TSymbol(string s) { any(RequiredConstantValue x).requiredSymbol(s) } or
1213
TBoolean(boolean b) { b in [false, true] } or
1314
TNil()
1415

@@ -26,4 +27,6 @@ class RequiredConstantValue extends MkRequiredConstantValue {
2627
predicate requiredComplex(float real, float imaginary) { none() }
2728

2829
predicate requiredString(string s) { none() }
30+
31+
predicate requiredSymbol(string s) { none() }
2932
}

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ module ExprNodes {
458458
final ExprCfgNode getKeywordArgument(string keyword) {
459459
exists(PairCfgNode n |
460460
e.hasCfgChild(e.getAnArgument(), this, n) and
461-
n.getKey().getExpr().(SymbolLiteral).getConstantValue().isString(keyword) and
461+
n.getKey().getExpr().getConstantValue().isSymbol(keyword) and
462462
result = n.getValue()
463463
)
464464
}
@@ -643,7 +643,19 @@ module ExprNodes {
643643
}
644644

645645
private class RequiredStringConstantValue extends RequiredConstantValue {
646-
override predicate requiredString(string s) { s = getStringlikeLiteralCfgNodeValue(_) }
646+
override predicate requiredString(string s) {
647+
exists(StringlikeLiteralCfgNode n |
648+
s = getStringlikeLiteralCfgNodeValue(n) and
649+
not n.getExpr() instanceof SymbolLiteral
650+
)
651+
}
652+
653+
override predicate requiredSymbol(string s) {
654+
exists(StringlikeLiteralCfgNode n |
655+
s = getStringlikeLiteralCfgNodeValue(n) and
656+
n.getExpr() instanceof SymbolLiteral
657+
)
658+
}
647659
}
648660

649661
/** A control-flow node that wraps a `StringlikeLiteral` AST expression. */
@@ -658,8 +670,10 @@ module ExprNodes {
658670
/** Gets a component of this `StringlikeLiteral` */
659671
StringComponentCfgNode getAComponent() { result = this.getComponent(_) }
660672

661-
final override ConstantValue::ConstantStringValue getConstantValue() {
662-
result.isString(getStringlikeLiteralCfgNodeValue(this))
673+
final override ConstantValue getConstantValue() {
674+
if this.getExpr() instanceof SymbolLiteral
675+
then result.isSymbol(getStringlikeLiteralCfgNodeValue(this))
676+
else result.isString(getStringlikeLiteralCfgNodeValue(this))
663677
}
664678
}
665679

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,14 @@ private class Argument extends CfgNodes::ExprCfgNode {
167167
exists(int i |
168168
this = call.getArgument(i) and
169169
not this.getExpr() instanceof BlockArgument and
170-
not exists(this.getExpr().(Pair).getKey().getConstantValue().getString()) and
170+
not exists(this.getExpr().(Pair).getKey().getConstantValue().getSymbol()) and
171171
arg.isPositional(i)
172172
)
173173
or
174174
exists(CfgNodes::ExprNodes::PairCfgNode p |
175175
p = call.getArgument(_) and
176176
this = p.getValue() and
177-
arg.isKeyword(p.getKey().getConstantValue().getString())
177+
arg.isKeyword(p.getKey().getConstantValue().getSymbol())
178178
)
179179
or
180180
this = call.getReceiver() and arg.isSelf()

0 commit comments

Comments
 (0)