Ruby: Replace getValueText with getConstantValue

This commit is contained in:
Tom Hvitved
2022-01-20 14:22:11 +01:00
parent fede7dd238
commit aa9cfebc65
37 changed files with 732 additions and 280 deletions

View File

@@ -239,7 +239,7 @@ module HTTP {
string getUrlPattern() {
exists(CfgNodes::ExprNodes::StringlikeLiteralCfgNode strNode |
this.getUrlPatternArg().getALocalSource() = DataFlow::exprNode(strNode) and
result = strNode.getExpr().getValueText()
result = strNode.getExpr().getConstantValue().getString()
)
}
@@ -364,7 +364,7 @@ module HTTP {
string getMimetype() {
exists(CfgNodes::ExprNodes::StringlikeLiteralCfgNode strNode |
this.getMimetypeOrContentTypeArg().getALocalSource() = DataFlow::exprNode(strNode) and
result = strNode.getExpr().getValueText().splitAt(";", 0)
result = strNode.getExpr().getConstantValue().getString().splitAt(";", 0)
)
or
not exists(this.getMimetypeOrContentTypeArg()) and

View File

@@ -41,7 +41,7 @@ class Call extends Expr instanceof CallImpl {
final Expr getKeywordArgument(string keyword) {
exists(Pair p |
p = this.getAnArgument() and
p.getKey().(SymbolLiteral).getValueText() = keyword and
p.getKey().(SymbolLiteral).getConstantValue().isString(keyword) and
result = p.getValue()
)
}

View File

@@ -1,9 +1,93 @@
private import codeql.ruby.AST
private import internal.AST
private import internal.Constant
private import internal.Module
private import internal.Variable
private import internal.TreeSitter
/** A constant value. */
class ConstantValue extends TConstantValue {
/** Gets a textual representation of this constant value. */
final string toString() {
result = this.getInt().toString()
or
result = this.getFloat().toString()
or
exists(int numerator, int denominator |
this.isRational(numerator, denominator) and
result = numerator + "/" + denominator
)
or
exists(float real, float imaginary |
this.isComplex(real, imaginary) and
result = real + "+" + imaginary + "i"
)
or
result = this.getString()
or
result = this.getBoolean().toString()
or
this.isNil() and result = "nil"
}
/** Gets the integer value, if this is an integer. */
int getInt() { this = TInt(result) }
/** Holds if this is the integer value `i`. */
predicate isInt(int i) { i = this.getInt() }
/** Gets the float value, if this is a float. */
float getFloat() { this = TFloat(result) }
/** Holds if this is the float value `f`. */
predicate isFloat(float f) { f = this.getFloat() }
/** Holds if this is the rational value `numerator / denominator`. */
predicate isRational(int numerator, int denominator) { this = TRational(numerator, denominator) }
/** Holds if this is the complex value `real + imaginary * i`. */
predicate isComplex(float real, float imaginary) { this = TComplex(real, imaginary) }
/** Gets the string value, if this is a string. */
string getString() { this = TString(result) }
/** Holds if this is the string value `s`. */
predicate isString(string s) { s = this.getString() }
/** Gets the Boolean value, if this is a Boolean. */
boolean getBoolean() { this = TBoolean(result) }
/** Holds if this is the Boolean value `b`. */
predicate isBoolean(boolean b) { b = this.getBoolean() }
/** Holds if this is the `nil` value. */
predicate isNil() { this = TNil() }
}
/** Provides different sub classes of `ConstantValue`. */
module ConstantValue {
/** A constant integer value. */
class ConstantIntegerValue extends ConstantValue, TInt { }
/** A constant float value. */
class ConstantFloatValue extends ConstantValue, TFloat { }
/** A constant rational value. */
class ConstantRationalValue extends ConstantValue, TRational { }
/** A constant complex value. */
class ConstantComplexValue extends ConstantValue, TComplex { }
/** A constant string value. */
class ConstantStringValue extends ConstantValue, TString { }
/** A constant Boolean value. */
class ConstantBooleanValue extends ConstantValue, TBoolean { }
/** A constant `nil` value. */
class ConstantNilValue extends ConstantValue, TNil { }
}
/** An access to a constant. */
class ConstantAccess extends Expr, TConstantAccess {
/** Gets the name of the constant being accessed. */
@@ -139,7 +223,7 @@ class ConstantReadAccess extends ConstantAccess {
result = lookupConst(resolveConstantReadAccess(this.getScopeExpr()), this.getName())
}
override string getValueText() { result = this.getValue().getValueText() }
final override ConstantValue getConstantValue() { result = this.getValue().getConstantValue() }
final override string getAPrimaryQlClass() { result = "ConstantReadAccess" }
}

View File

@@ -1,5 +1,6 @@
private import codeql.ruby.AST
private import codeql.ruby.CFG
private import codeql.ruby.ast.Constant
private import internal.AST
private import internal.Expr
private import internal.TreeSitter
@@ -10,9 +11,16 @@ private import internal.TreeSitter
* This is the root QL class for all expressions.
*/
class Expr extends Stmt, TExpr {
/** Gets the textual (constant) value of this expression, if any. */
string getValueText() {
forex(CfgNodes::ExprCfgNode n | n = this.getAControlFlowNode() | result = n.getValueText())
/**
* DEPRECATED: Use `getConstantValue` instead.
*
* Gets the textual (constant) value of this expression, if any.
*/
deprecated string getValueText() { result = this.getConstantValue().toString() }
/** Gets the constant value of this expression, if any. */
ConstantValue getConstantValue() {
forex(CfgNodes::ExprCfgNode n | n = this.getAControlFlowNode() | result = n.getConstantValue())
}
}
@@ -456,10 +464,10 @@ class StringConcatenation extends Expr, TStringConcatenation {
* ```
*/
final string getConcatenatedValueText() {
forall(StringLiteral c | c = this.getString(_) | exists(c.getValueText())) and
forall(StringLiteral c | c = this.getString(_) | exists(c.getConstantValue().getString())) and
result =
concat(string valueText, int i |
valueText = this.getString(i).getValueText()
valueText = this.getString(i).getConstantValue().getString()
|
valueText order by i
)

View File

@@ -1,6 +1,7 @@
private import codeql.ruby.AST
private import codeql.ruby.security.performance.RegExpTreeView as RETV
private import internal.AST
private import internal.Constant
private import internal.Scope
private import internal.TreeSitter
private import codeql.ruby.controlflow.CfgNodes
@@ -39,52 +40,60 @@ class IntegerLiteral extends NumericLiteral, TIntegerLiteral {
/** Gets the numerical value of this integer literal. */
int getValue() { none() }
final override string toString() { result = this.getValueText() }
final override ConstantValue::ConstantIntegerValue getConstantValue() {
result.isInt(this.getValue())
}
final override string getAPrimaryQlClass() { result = "IntegerLiteral" }
}
private int parseInteger(Ruby::Integer i) {
exists(string s, string values, string str |
s = i.getValue().toLowerCase() and
(
s.matches("0b%") and
values = "01" and
str = s.suffix(2)
or
s.matches("0x%") and
values = "0123456789abcdef" and
str = s.suffix(2)
or
s.charAt(0) = "0" and
not s.charAt(1) = ["b", "x", "o"] and
values = "01234567" and
str = s.suffix(1)
or
s.matches("0o%") and
values = "01234567" and
str = s.suffix(2)
or
s.charAt(0) != "0" and values = "0123456789" and str = s
)
|
result =
sum(int index, string c, int v, int exp |
c = str.replaceAll("_", "").charAt(index) and
v = values.indexOf(c.toLowerCase()) and
exp = str.replaceAll("_", "").length() - index - 1
|
v * values.length().pow(exp)
)
)
}
private class RequiredIntegerConstantValue extends RequiredConstantValue {
override predicate requiredInt(int i) { i = any(IntegerLiteral il).getValue() }
}
private class IntegerLiteralReal extends IntegerLiteral, TIntegerLiteralReal {
private Ruby::Integer g;
IntegerLiteralReal() { this = TIntegerLiteralReal(g) }
final override string getValueText() { result = g.getValue() }
final override int getValue() { result = parseInteger(g) }
final override int getValue() {
exists(string s, string values, string str |
s = this.getValueText().toLowerCase() and
(
s.matches("0b%") and
values = "01" and
str = s.suffix(2)
or
s.matches("0x%") and
values = "0123456789abcdef" and
str = s.suffix(2)
or
s.charAt(0) = "0" and
not s.charAt(1) = ["b", "x", "o"] and
values = "01234567" and
str = s.suffix(1)
or
s.matches("0o%") and
values = "01234567" and
str = s.suffix(2)
or
s.charAt(0) != "0" and values = "0123456789" and str = s
)
|
result =
sum(int index, string c, int v, int exp |
c = str.replaceAll("_", "").charAt(index) and
v = values.indexOf(c.toLowerCase()) and
exp = str.replaceAll("_", "").length() - index - 1
|
v * values.length().pow(exp)
)
)
}
final override string toString() { result = g.getValue() }
}
private class IntegerLiteralSynth extends IntegerLiteral, TIntegerLiteralSynth {
@@ -92,9 +101,16 @@ private class IntegerLiteralSynth extends IntegerLiteral, TIntegerLiteralSynth {
IntegerLiteralSynth() { this = TIntegerLiteralSynth(_, _, value) }
final override string getValueText() { result = value.toString() }
final override int getValue() { result = value }
final override string toString() { result = value.toString() }
}
// TODO: implement properly
private float parseFloat(Ruby::Float f) { result = f.getValue().toFloat() }
private class RequiredFloatConstantValue extends RequiredConstantValue {
override predicate requiredFloat(float f) { f = parseFloat(_) }
}
/**
@@ -110,13 +126,35 @@ class FloatLiteral extends NumericLiteral, TFloatLiteral {
FloatLiteral() { this = TFloatLiteral(g) }
final override string getValueText() { result = g.getValue() }
final override ConstantValue::ConstantFloatValue getConstantValue() {
result.isFloat(parseFloat(g))
}
final override string toString() { result = this.getValueText() }
final override string toString() { result = g.getValue() }
final override string getAPrimaryQlClass() { result = "FloatLiteral" }
}
private predicate isRationalValue(Ruby::Rational r, int numerator, int denominator) {
numerator = parseInteger(r.getChild()) and
denominator = 1
or
exists(Ruby::Float f, string regex, string before, string after |
f = r.getChild() and
regex = "([^.]*)\\.(.*)" and
before = f.getValue().regexpCapture(regex, 1) and
after = f.getValue().regexpCapture(regex, 2) and
numerator = before.toInt() * denominator + after.toInt() and
denominator = 10.pow(after.length())
)
}
private class RequiredRationalConstantValue extends RequiredConstantValue {
override predicate requiredRational(int numerator, int denominator) {
isRationalValue(_, numerator, denominator)
}
}
/**
* A rational literal.
*
@@ -129,13 +167,32 @@ class RationalLiteral extends NumericLiteral, TRationalLiteral {
RationalLiteral() { this = TRationalLiteral(g) }
final override string getValueText() { result = g.getChild().(Ruby::Token).getValue() + "r" }
final override ConstantValue::ConstantRationalValue getConstantValue() {
exists(int numerator, int denominator |
isRationalValue(g, numerator, denominator) and
result.isRational(numerator, denominator)
)
}
final override string toString() { result = this.getValueText() }
final override string toString() { result = g.getChild().(Ruby::Token).getValue() + "r" }
final override string getAPrimaryQlClass() { result = "RationalLiteral" }
}
private float getComplexValue(Ruby::Complex c) {
exists(string s |
s = c.getValue() and
result = s.prefix(s.length() - 1).toFloat()
)
}
private class RequiredComplexConstantValue extends RequiredConstantValue {
override predicate requiredComplex(float real, float imaginary) {
real = 0 and
imaginary = getComplexValue(_)
}
}
/**
* A complex literal.
*
@@ -148,9 +205,11 @@ class ComplexLiteral extends NumericLiteral, TComplexLiteral {
ComplexLiteral() { this = TComplexLiteral(g) }
final override string getValueText() { result = g.getValue() }
final override ConstantValue::ConstantComplexValue getConstantValue() {
result.isComplex(0, getComplexValue(g))
}
final override string toString() { result = this.getValueText() }
final override string toString() { result = g.getValue() }
final override string getAPrimaryQlClass() { result = "ComplexLiteral" }
}
@@ -161,9 +220,9 @@ class NilLiteral extends Literal, TNilLiteral {
NilLiteral() { this = TNilLiteral(g) }
final override string getValueText() { result = g.getValue() }
final override ConstantValue::ConstantNilValue getConstantValue() { any() }
final override string toString() { result = this.getValueText() }
final override string toString() { result = g.getValue() }
final override string getAPrimaryQlClass() { result = "NilLiteral" }
}
@@ -180,8 +239,6 @@ class NilLiteral extends Literal, TNilLiteral {
class BooleanLiteral extends Literal, TBooleanLiteral {
final override string getAPrimaryQlClass() { result = "BooleanLiteral" }
final override string toString() { result = this.getValueText() }
/** Holds if the Boolean literal is `true` or `TRUE`. */
predicate isTrue() { none() }
@@ -194,6 +251,10 @@ class BooleanLiteral extends Literal, TBooleanLiteral {
or
this.isFalse() and result = false
}
final override ConstantValue::ConstantBooleanValue getConstantValue() {
result.isBoolean(this.getValue())
}
}
private class TrueLiteral extends BooleanLiteral, TTrueLiteral {
@@ -201,7 +262,7 @@ private class TrueLiteral extends BooleanLiteral, TTrueLiteral {
TrueLiteral() { this = TTrueLiteral(g) }
final override string getValueText() { result = g.getValue() }
final override string toString() { result = g.getValue() }
final override predicate isTrue() { any() }
}
@@ -211,11 +272,15 @@ private class FalseLiteral extends BooleanLiteral, TFalseLiteral {
FalseLiteral() { this = TFalseLiteral(g) }
final override string getValueText() { result = g.getValue() }
final override string toString() { result = g.getValue() }
final override predicate isFalse() { any() }
}
private class RequiredStringConstantValue extends RequiredConstantValue {
override predicate requiredString(string s) { s = "UTF-8" }
}
/**
* An `__ENCODING__` literal.
*/
@@ -225,7 +290,11 @@ class EncodingLiteral extends Literal, TEncoding {
final override string toString() { result = "__ENCODING__" }
// TODO: return the encoding defined by a magic encoding: comment, if any.
override string getValueText() { result = "UTF-8" }
override ConstantValue::ConstantStringValue getConstantValue() { result.isString("UTF-8") }
}
private class RequiredIntegerConstantValue2 extends RequiredConstantValue {
override predicate requiredInt(int i) { i = any(LineLiteral ll).getLocation().getStartLine() }
}
/**
@@ -236,7 +305,15 @@ class LineLiteral extends Literal, TLine {
final override string toString() { result = "__LINE__" }
override string getValueText() { result = this.getLocation().getStartLine().toString() }
final override ConstantValue::ConstantIntegerValue getConstantValue() {
result.isInt(this.getLocation().getStartLine())
}
}
private class RequiredStringConstantValue2 extends RequiredConstantValue {
override predicate requiredString(string s) {
s = any(FileLiteral fl).getLocation().getFile().getAbsolutePath()
}
}
/**
@@ -247,7 +324,9 @@ class FileLiteral extends Literal, TFile {
final override string toString() { result = "__FILE__" }
override string getValueText() { result = this.getLocation().getFile().getAbsolutePath() }
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(this.getLocation().getFile().getAbsolutePath())
}
}
/**
@@ -256,17 +335,28 @@ class FileLiteral extends Literal, TFile {
*/
class StringComponent extends AstNode, TStringComponent {
/**
* DEPRECATED: Use `getConstantValue` instead.
*
* Gets the source text for this string component. Has no result if this is
* a `StringInterpolationComponent`.
*/
string getValueText() { none() }
deprecated string getValueText() { result = this.getConstantValue().toString() }
/** Gets the constant value of this string component, if any. */
ConstantValue::ConstantStringValue getConstantValue() { none() }
}
private class RequiredStringConstantValue3 extends RequiredConstantValue {
override predicate requiredString(string s) {
s = any(Ruby::Token t | exists(TStringTextComponentNonRegexp(t))).getValue()
}
}
/**
* A component of a string (or string-like) literal that is simply text.
*
* For example, the following string literals all contain `StringTextComponent`
* components whose `getValueText()` returns `"foo"`:
* components whose `getConstantValue()` returns `"foo"`:
*
* ```rb
* 'foo'
@@ -281,11 +371,19 @@ class StringTextComponent extends StringComponent, TStringTextComponentNonRegexp
final override string toString() { result = g.getValue() }
final override string getValueText() { result = g.getValue() }
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(g.getValue())
}
final override string getAPrimaryQlClass() { result = "StringTextComponent" }
}
private class RequiredStringConstantValue4 extends RequiredConstantValue {
override predicate requiredString(string s) {
s = any(Ruby::Token t | exists(TStringEscapeSequenceComponentNonRegexp(t))).getValue()
}
}
/**
* An escape sequence component of a string or string-like literal.
*/
@@ -296,7 +394,9 @@ class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequen
final override string toString() { result = g.getValue() }
final override string getValueText() { result = g.getValue() }
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(g.getValue())
}
final override string getAPrimaryQlClass() { result = "StringEscapeSequenceComponent" }
}
@@ -314,7 +414,9 @@ class StringInterpolationComponent extends StringComponent, StmtSequence,
final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
final override string getValueText() { none() }
deprecated final override string getValueText() { none() }
final override ConstantValue::ConstantStringValue getConstantValue() { none() }
final override string getAPrimaryQlClass() { result = "StringInterpolationComponent" }
}
@@ -327,15 +429,36 @@ private class TRegExpComponent =
* The base class for a component of a regular expression literal.
*/
class RegExpComponent extends AstNode, TRegExpComponent {
/** Gets the source text for this regex component, if any. */
string getValueText() { none() }
/**
* DEPRECATED: Use `getConstantValue` instead.
*
* Gets the source text for this regex component, if any.
*/
deprecated string getValueText() { result = this.getConstantValue().toString() }
/** Gets the constant value of this regex component, if any. */
ConstantValue::ConstantStringValue getConstantValue() { none() }
}
// Exclude components that are children of a free-spacing regex.
// We do this because `ParseRegExp.qll` cannot handle free-spacing regexes.
private string getRegExpTextComponentValue(RegExpTextComponent c) {
exists(Ruby::Token t |
c = TStringTextComponentRegexp(t) and
not c.getParent().(RegExpLiteral).hasFreeSpacingFlag() and
result = t.getValue()
)
}
private class RequiredStringConstantValue5 extends RequiredConstantValue {
override predicate requiredString(string s) { s = getRegExpTextComponentValue(_) }
}
/**
* A component of a regex literal that is simply text.
*
* For example, the following regex literals all contain `RegExpTextComponent`
* components whose `getValueText()` returns `"foo"`:
* components whose `getConstantValue()` returns `"foo"`:
*
* ```rb
* 'foo'
@@ -350,15 +473,27 @@ class RegExpTextComponent extends RegExpComponent, TStringTextComponentRegexp {
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 ConstantValue::ConstantStringValue getConstantValue() {
result.isString(getRegExpTextComponentValue(this))
}
final override string getAPrimaryQlClass() { result = "RegExpTextComponent" }
}
// Exclude components that are children of a free-spacing regex.
// We do this because `ParseRegExp.qll` cannot handle free-spacing regexes.
private string getRegExpEscapeSequenceComponentValue(RegExpEscapeSequenceComponent c) {
exists(Ruby::EscapeSequence e |
c = TStringEscapeSequenceComponentRegexp(e) and
not c.getParent().(RegExpLiteral).hasFreeSpacingFlag() and
result = e.getValue()
)
}
private class RequiredStringConstantValue6 extends RequiredConstantValue {
override predicate requiredString(string s) { s = getRegExpEscapeSequenceComponentValue(_) }
}
/**
* An escape sequence component of a regex literal.
*/
@@ -369,10 +504,8 @@ class RegExpEscapeSequenceComponent extends RegExpComponent, TStringEscapeSequen
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 ConstantValue::ConstantStringValue getConstantValue() {
result.isString(getRegExpEscapeSequenceComponentValue(this))
}
final override string getAPrimaryQlClass() { result = "RegExpEscapeSequenceComponent" }
@@ -391,7 +524,9 @@ class RegExpInterpolationComponent extends RegExpComponent, StmtSequence,
final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
final override string getValueText() { none() }
deprecated final override string getValueText() { none() }
final override ConstantValue::ConstantStringValue getConstantValue() { none() }
final override string getAPrimaryQlClass() { result = "RegExpInterpolationComponent" }
}
@@ -623,13 +758,21 @@ class SymbolLiteral extends StringlikeLiteral, TSymbolLiteral {
}
}
// Tree-sitter gives us value text including the colon, which we skip.
private string getSimpleSymbolValue(Ruby::SimpleSymbol ss) { result = ss.getValue().suffix(1) }
private class RequiredStringConstantValue7 extends RequiredConstantValue {
override predicate requiredString(string s) { s = getSimpleSymbolValue(_) }
}
private class SimpleSymbolLiteral extends SymbolLiteral, TSimpleSymbolLiteral {
private Ruby::SimpleSymbol g;
SimpleSymbolLiteral() { this = TSimpleSymbolLiteral(g) }
// Tree-sitter gives us value text including the colon, which we skip.
final override string getValueText() { result = g.getValue().suffix(1) }
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(getSimpleSymbolValue(g))
}
final override string toString() { result = g.getValue() }
}
@@ -652,14 +795,20 @@ private class BareSymbolLiteral extends ComplexSymbolLiteral, TBareSymbolLiteral
final override StringComponent getComponent(int i) { toGenerated(result) = g.getChild(i) }
}
private class RequiredStringConstantValue8 extends RequiredConstantValue {
override predicate requiredString(string s) { s = any(Ruby::HashKeySymbol h).getValue() }
}
private class HashKeySymbolLiteral extends SymbolLiteral, THashKeySymbolLiteral {
private Ruby::HashKeySymbol g;
HashKeySymbolLiteral() { this = THashKeySymbolLiteral(g) }
final override string getValueText() { result = g.getValue() }
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(g.getValue())
}
final override string toString() { result = ":" + this.getValueText() }
final override string toString() { result = ":" + g.getValue() }
}
/**
@@ -680,6 +829,10 @@ class SubshellLiteral extends StringlikeLiteral, TSubshellLiteral {
final override StringComponent getComponent(int i) { toGenerated(result) = g.getChild(i) }
}
private class RequiredStringConstantValue9 extends RequiredConstantValue {
override predicate requiredString(string s) { s = any(Ruby::Character c).getValue() }
}
/**
* A character literal.
*
@@ -693,7 +846,9 @@ class CharacterLiteral extends Literal, TCharacterLiteral {
CharacterLiteral() { this = TCharacterLiteral(g) }
final override string getValueText() { result = g.getValue() }
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(g.getValue())
}
final override string toString() { result = g.getValue() }
@@ -970,16 +1125,24 @@ class MethodName extends Literal {
final override string getAPrimaryQlClass() { result = "MethodName" }
}
private string getMethodName(MethodName::Token t) {
result = t.(Ruby::Token).getValue()
or
result = t.(Ruby::Setter).getName().getValue() + "="
}
private class RequiredStringConstantValue10 extends RequiredConstantValue {
override predicate requiredString(string s) { s = getMethodName(_) }
}
private class TokenMethodName extends MethodName, TTokenMethodName {
private MethodName::Token g;
TokenMethodName() { this = TTokenMethodName(g) }
final override string getValueText() {
result = g.(Ruby::Token).getValue()
or
result = g.(Ruby::Setter).getName().getValue() + "="
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(getMethodName(g))
}
final override string toString() { result = this.getValueText() }
final override string toString() { result = getMethodName(g) }
}

View File

@@ -53,7 +53,7 @@ private class MethodModifier extends MethodCall {
predicate modifiesMethod(Namespace n, string name) {
this = n.getAStmt() and
[
this.getMethodArgument().(StringlikeLiteral).getValueText(),
this.getMethodArgument().(StringlikeLiteral).getConstantValue().getString(),
this.getMethodArgument().(MethodBase).getName()
] = name
}

View File

@@ -271,7 +271,7 @@ class HashPattern extends CasePattern, THashPattern {
/** Gets the value for a given key name. */
CasePattern getValueByKey(string key) {
exists(int i | key = this.getKey(i).getValueText() and result = this.getValue(i))
exists(int i | this.getKey(i).getConstantValue().isString(key) and result = this.getValue(i))
}
/**

View File

@@ -0,0 +1,29 @@
cached
newtype TConstantValue =
TInt(int i) { any(RequiredConstantValue x).requiredInt(i) } or
TFloat(float f) { any(RequiredConstantValue x).requiredFloat(f) } or
TRational(int numerator, int denominator) {
any(RequiredConstantValue x).requiredRational(numerator, denominator)
} or
TComplex(float real, float imaginary) {
any(RequiredConstantValue x).requiredComplex(real, imaginary)
} or
TString(string s) { any(RequiredConstantValue x).requiredString(s) } or
TBoolean(boolean b) { b in [false, true] } or
TNil()
private newtype TRequiredConstantValue = MkRequiredConstantValue()
class RequiredConstantValue extends MkRequiredConstantValue {
string toString() { none() }
predicate requiredInt(int i) { none() }
predicate requiredFloat(float f) { none() }
predicate requiredRational(int numerator, int denominator) { none() }
predicate requiredComplex(float real, float imaginary) { none() }
predicate requiredString(string s) { none() }
}

View File

@@ -3,6 +3,7 @@
private import codeql.ruby.AST
private import codeql.ruby.controlflow.BasicBlocks
private import codeql.ruby.dataflow.SSA
private import codeql.ruby.ast.internal.Constant
private import ControlFlowGraph
private import internal.ControlFlowGraphImpl
private import internal.Splitting
@@ -107,9 +108,16 @@ class ExprCfgNode extends AstCfgNode {
)
}
/** Gets the textual (constant) value of this expression, if any. */
/**
* DEPRECATED: Use `getConstantValue` instead.
*
* Gets the textual (constant) value of this expression, if any.
*/
deprecated string getValueText() { result = this.getConstantValue().toString() }
/** Gets the constant value of this expression, if any. */
cached
string getValueText() { result = this.getSource().getValueText() }
ConstantValue getConstantValue() { result = this.getSource().getConstantValue() }
}
/** A control-flow node that wraps a return-like statement. */
@@ -129,14 +137,16 @@ class ReturningCfgNode extends AstCfgNode {
class StringComponentCfgNode extends AstCfgNode {
StringComponentCfgNode() { this.getNode() instanceof StringComponent }
string getValueText() { result = this.getNode().(StringComponent).getValueText() }
/** Gets the constant value of this string component. */
ConstantValue getConstantValue() { result = this.getNode().(StringComponent).getConstantValue() }
}
/** 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() }
/** Gets the constant value of this regex component. */
ConstantValue getConstantValue() { result = this.getNode().(RegExpComponent).getConstantValue() }
}
private AstNode desugar(AstNode n) {
@@ -195,7 +205,7 @@ module ExprNodes {
override Literal getExpr() { result = super.getExpr() }
override string getValueText() { result = e.getValueText() }
override ConstantValue getConstantValue() { result = e.getConstantValue() }
}
private class AssignExprChildMapping extends ExprChildMapping, AssignExpr {
@@ -229,6 +239,125 @@ module ExprNodes {
final ExprCfgNode getAnOperand() { e.hasCfgChild(e.getAnOperand(), this, result) }
}
private predicate unaryConstFold(UnaryOperationCfgNode unop, string op, ConstantValue value) {
value = unop.getOperand().getConstantValue() and
op = unop.getExpr().getOperator()
}
private class RequiredUnaryConstantValue extends RequiredConstantValue {
override predicate requiredInt(int i) {
exists(ConstantValue value |
unaryConstFold(_, "-", value) and
i = -value.getInt()
)
}
override predicate requiredFloat(float f) {
exists(ConstantValue value |
unaryConstFold(_, "-", value) and
f = -value.getFloat()
)
}
}
/** A control-flow node that wraps a `UnaryOperation` AST expression. */
class UnaryOperationCfgNode extends OperationCfgNode {
private UnaryOperation uo;
UnaryOperationCfgNode() { e = uo }
override UnaryOperation getExpr() { result = super.getExpr() }
/** Gets the operand of this unary operation. */
final ExprCfgNode getOperand() { e.hasCfgChild(uo.getOperand(), this, result) }
final override ConstantValue getConstantValue() {
exists(string op, ConstantValue value | unaryConstFold(this, op, value) |
op = "+" and
result = value
or
op = "-" and
(
result.isInt(-value.getInt())
or
result.isFloat(-value.getFloat())
)
)
}
}
private predicate binaryConstFold(
BinaryOperationCfgNode binop, string op, ConstantValue left, ConstantValue right
) {
left = binop.getLeftOperand().getConstantValue() and
right = binop.getRightOperand().getConstantValue() and
op = binop.getExpr().getOperator()
}
private class RequiredBinaryConstantValue extends RequiredConstantValue {
override predicate requiredInt(int i) {
exists(string op, ConstantValue left, ConstantValue right |
binaryConstFold(_, op, left, right)
|
op = "+" and
i = left.getInt() + right.getInt()
or
op = "-" and
i = left.getInt() - right.getInt()
or
op = "*" and
i = left.getInt() * right.getInt()
or
op = "/" and
i = left.getInt() / right.getInt()
)
}
override predicate requiredFloat(float f) {
exists(string op, ConstantValue left, ConstantValue right |
binaryConstFold(_, op, left, right)
|
op = "+" and
f =
[
left.getFloat() + right.getFloat(), left.getInt() + right.getFloat(),
left.getFloat() + right.getInt()
]
or
op = "-" and
f =
[
left.getFloat() - right.getFloat(), left.getInt() - right.getFloat(),
left.getFloat() - right.getInt()
]
or
op = "*" and
f =
[
left.getFloat() * right.getFloat(), left.getInt() * right.getFloat(),
left.getFloat() * right.getInt()
]
or
op = "/" and
f =
[
left.getFloat() / right.getFloat(), left.getInt() / right.getFloat(),
left.getFloat() / right.getInt()
]
)
}
override predicate requiredString(string s) {
exists(string op, ConstantValue left, ConstantValue right |
binaryConstFold(_, op, left, right)
|
op = "+" and
s = left.getString() + right.getString() and
s.length() <= 10000
)
}
}
/** A control-flow node that wraps a `BinaryOperation` AST expression. */
class BinaryOperationCfgNode extends OperationCfgNode {
private BinaryOperation bo;
@@ -243,56 +372,54 @@ module ExprNodes {
/** Gets the right operand of this binary operation. */
final ExprCfgNode getRightOperand() { e.hasCfgChild(bo.getRightOperand(), this, result) }
final override string getValueText() {
exists(string left, string right, string op |
left = this.getLeftOperand().getValueText() and
right = this.getRightOperand().getValueText() and
op = this.getExpr().getOperator()
final override ConstantValue getConstantValue() {
exists(string op, ConstantValue left, ConstantValue right |
binaryConstFold(this, op, left, right)
|
op = "+" and
(
result = (left.toInt() + right.toInt()).toString()
result.isInt(left.getInt() + right.getInt())
or
not (exists(left.toInt()) and exists(right.toInt())) and
result = (left.toFloat() + right.toFloat()).toString()
result
.isFloat([
left.getFloat() + right.getFloat(), left.getInt() + right.getFloat(),
left.getFloat() + right.getInt()
])
or
not (exists(left.toFloat()) and exists(right.toFloat())) and
exists(int l, int r, int limit |
l = left.length() and
r = right.length() and
limit = 10000
|
if l > limit
then result = left.prefix(limit) + "..."
else
if l + r > limit
then result = left + right.prefix(limit - l) + "..."
else result = left + right
)
result.isString(left.getString() + right.getString())
)
or
op = "-" and
(
result = (left.toInt() - right.toInt()).toString()
result.isInt(left.getInt() - right.getInt())
or
not (exists(left.toInt()) and exists(right.toInt())) and
result = (left.toFloat() - right.toFloat()).toString()
result
.isFloat([
left.getFloat() - right.getFloat(), left.getInt() - right.getFloat(),
left.getFloat() - right.getInt()
])
)
or
op = "*" and
(
result = (left.toInt() * right.toInt()).toString()
result.isInt(left.getInt() * right.getInt())
or
not (exists(left.toInt()) and exists(right.toInt())) and
result = (left.toFloat() * right.toFloat()).toString()
result
.isFloat([
left.getFloat() * right.getFloat(), left.getInt() * right.getFloat(),
left.getFloat() * right.getInt()
])
)
or
op = "/" and
(
result = (left.toInt() / right.toInt()).toString()
result.isInt(left.getInt() / right.getInt())
or
not (exists(left.toInt()) and exists(right.toInt())) and
result = (left.toFloat() / right.toFloat()).toString()
result
.isFloat([
left.getFloat() / right.getFloat(), left.getInt() / right.getFloat(),
left.getFloat() / right.getInt()
])
)
)
}
@@ -331,7 +458,7 @@ module ExprNodes {
final ExprCfgNode getKeywordArgument(string keyword) {
exists(PairCfgNode n |
e.hasCfgChild(e.getAnArgument(), this, n) and
n.getKey().getExpr().(SymbolLiteral).getValueText() = keyword and
n.getKey().getExpr().(SymbolLiteral).getConstantValue().isString(keyword) and
result = n.getValue()
)
}
@@ -400,7 +527,7 @@ module ExprNodes {
/** Gets the scope expression. */
final ExprCfgNode getScopeExpr() { e.hasCfgChild(e.getScopeExpr(), this, result) }
override string getValueText() { result = this.getExpr().getValueText() }
override ConstantValue getConstantValue() { result = this.getExpr().getConstantValue() }
}
private class StmtSequenceChildMapping extends ExprChildMapping, StmtSequence {
@@ -478,7 +605,9 @@ module ExprNodes {
// If last statement in the interpolation is a constant or local variable read,
// we attempt to look up its string value.
// If there's a result, we return that as the string value of the interpolation.
final override string getValueText() { result = this.getLastStmt().getValueText() }
final override ConstantValue getConstantValue() {
result = this.getLastStmt().getConstantValue()
}
}
/** A control-flow node that wraps a `RegExpInterpolationComponent` AST expression. */
@@ -486,14 +615,37 @@ module ExprNodes {
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() }
// attempt to look up its definition and return the definition's `getConstantValue()`.
final override ConstantValue getConstantValue() {
result = this.getLastStmt().getConstantValue()
}
}
private class StringlikeLiteralChildMapping extends ExprChildMapping, StringlikeLiteral {
override predicate relevantChild(AstNode n) { n = this.getComponent(_) }
}
pragma[nomagic]
private string getStringComponentCfgNodeValue(StringComponentCfgNode c) {
result = c.getConstantValue().toString()
}
// 0 components results in the empty string
// if all interpolations have a known string value, we will get a result
language[monotonicAggregates]
private string getStringlikeLiteralCfgNodeValue(StringlikeLiteralCfgNode n) {
result =
concat(StringComponentCfgNode c, int i |
c = n.getComponent(i)
|
getStringComponentCfgNodeValue(c) order by i
)
}
private class RequiredStringConstantValue extends RequiredConstantValue {
override predicate requiredString(string s) { s = getStringlikeLiteralCfgNodeValue(_) }
}
/** A control-flow node that wraps a `StringlikeLiteral` AST expression. */
class StringlikeLiteralCfgNode extends ExprCfgNode {
override StringlikeLiteralChildMapping e;
@@ -506,16 +658,8 @@ module ExprNodes {
/** Gets a component of this `StringlikeLiteral` */
StringComponentCfgNode getAComponent() { result = this.getComponent(_) }
// 0 components results in the empty string
// if all interpolations have a known string value, we will get a result
language[monotonicAggregates]
override string getValueText() {
result =
concat(StringComponentCfgNode c, int i |
c = this.getComponent(i)
|
c.getValueText() order by i
)
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(getStringlikeLiteralCfgNodeValue(this))
}
}
@@ -530,6 +674,25 @@ module ExprNodes {
override predicate relevantChild(AstNode n) { n = this.getComponent(_) }
}
pragma[nomagic]
private string getRegExpComponentCfgNodeValue(RegExpComponentCfgNode c) {
result = c.getConstantValue().toString()
}
language[monotonicAggregates]
private string getRegExpLiteralCfgNodeValue(RegExpLiteralCfgNode n) {
result =
concat(RegExpComponentCfgNode c, int i |
c = n.getComponent(i)
|
getRegExpComponentCfgNodeValue(c) order by i
)
}
private class RequiredStringConstantValue2 extends RequiredConstantValue {
override predicate requiredString(string s) { s = getRegExpLiteralCfgNodeValue(_) }
}
/** A control-flow node that wraps a `RegExpLiteral` AST expression. */
class RegExpLiteralCfgNode extends ExprCfgNode {
override RegExpLiteralChildMapping e;
@@ -538,14 +701,8 @@ module ExprNodes {
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
)
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(getRegExpLiteralCfgNodeValue(this))
}
}

View File

@@ -167,14 +167,14 @@ private class Argument extends CfgNodes::ExprCfgNode {
exists(int i |
this = call.getArgument(i) and
not this.getExpr() instanceof BlockArgument and
not exists(this.getExpr().(Pair).getKey().getValueText()) and
not exists(this.getExpr().(Pair).getKey().getConstantValue().getString()) and
arg.isPositional(i)
)
or
exists(CfgNodes::ExprNodes::PairCfgNode p |
p = call.getArgument(_) and
this = p.getValue() and
arg.isKeyword(p.getKey().getValueText())
arg.isKeyword(p.getKey().getConstantValue().getString())
)
or
this = call.getReceiver() and arg.isSelf()

View File

@@ -176,7 +176,7 @@ class RedirectToCall extends ActionControllerContextCall {
/** Gets the `ActionControllerActionMethod` to redirect to, if any */
ActionControllerActionMethod getRedirectActionMethod() {
exists(string methodName |
methodName = this.getKeywordArgument("action").(StringlikeLiteral).getValueText() and
this.getKeywordArgument("action").getConstantValue().isString(methodName) and
methodName = result.getName() and
result.getEnclosingModule() = this.getControllerClass()
)
@@ -225,7 +225,7 @@ class ActionControllerHelperMethod extends Method {
this.getEnclosingModule() = controllerClass and
exists(MethodCall helperMethodMarker |
helperMethodMarker.getMethodName() = "helper_method" and
helperMethodMarker.getAnArgument().(StringlikeLiteral).getValueText() = this.getName() and
helperMethodMarker.getAnArgument().getConstantValue().isString(this.getName()) and
helperMethodMarker.getEnclosingModule() = controllerClass
)
}
@@ -291,7 +291,7 @@ class ActionControllerSkipForgeryProtectionCall extends CSRFProtectionSetting::R
call.getMethodName() = "skip_forgery_protection"
or
call.getMethodName() = "skip_before_action" and
call.getAnArgument().(SymbolLiteral).getValueText() = "verify_authenticity_token"
call.getAnArgument().getConstantValue().isString("verify_authenticity_token")
)
}
@@ -309,7 +309,9 @@ private class ActionControllerProtectFromForgeryCall extends CSRFProtectionSetti
callExpr.getMethodName() = "protect_from_forgery"
}
private string getWithValueText() { result = callExpr.getKeywordArgument("with").getValueText() }
private string getWithValueText() {
result = callExpr.getKeywordArgument("with").getConstantValue().getString()
}
// Calls without `with: :exception` can allow for bypassing CSRF protection
// in some scenarios.

View File

@@ -81,7 +81,9 @@ abstract class RenderCall extends MethodCall {
result = [this.getKeywordArgument(["partial", "template", "action"]), this.getArgument(0)]
}
private string getTemplatePathValue() { result = this.getTemplatePathArgument().getValueText() }
private string getTemplatePathValue() {
result = this.getTemplatePathArgument().getConstantValue().getString()
}
// everything up to and including the final slash, but ignoring any leading slash
private string getSubPath() {

View File

@@ -28,7 +28,7 @@ private DataFlow::Node ioInstance() {
// will execute a shell command and read its output rather than reading from the
// filesystem.
private predicate pathArgSpawnsSubprocess(Expr arg) {
arg.(StringlikeLiteral).getValueText().charAt(0) = "|"
arg.getConstantValue().getString().charAt(0) = "|"
}
private DataFlow::Node fileInstanceInstantiation() {

View File

@@ -300,7 +300,7 @@ class GraphqlFieldDefinitionMethodCall extends GraphqlSchemaObjectClassMethodCal
GraphqlFieldDefinitionMethodCall() { this.getMethodName() = "field" }
/** Gets the name of this GraphQL field. */
string getFieldName() { result = this.getArgument(0).getValueText() }
string getFieldName() { result = this.getArgument(0).getConstantValue().getString() }
}
/**
@@ -336,7 +336,7 @@ private class GraphqlFieldArgumentDefinitionMethodCall extends GraphqlSchemaObje
string getFieldName() { result = this.getFieldDefinition().getFieldName() }
/** Gets the name of the argument (i.e. the first argument to this `argument` method call) */
string getArgumentName() { result = this.getArgument(0).(SymbolLiteral).getValueText() }
string getArgumentName() { result = this.getArgument(0).getConstantValue().getString() }
}
/**
@@ -385,7 +385,7 @@ class GraphqlFieldResolutionMethod extends Method, HTTP::Server::RequestHandler:
exists(GraphqlFieldDefinitionMethodCall defn |
// field :foo, resolver_method: :custom_method
// def custom_method(...)
defn.getKeywordArgument("resolver_method").(SymbolLiteral).getValueText() = this.getName()
defn.getKeywordArgument("resolver_method").getConstantValue().isString(this.getName())
or
// field :foo
// def foo(...)
@@ -396,7 +396,7 @@ class GraphqlFieldResolutionMethod extends Method, HTTP::Server::RequestHandler:
/** Gets the method call which is the definition of the field corresponding to this resolver method. */
GraphqlFieldDefinitionMethodCall getDefinition() {
result.getKeywordArgument("resolver_method").(SymbolLiteral).getValueText() = this.getName()
result.getKeywordArgument("resolver_method").getConstantValue().isString(this.getName())
or
not exists(result.getKeywordArgument("resolver_method").(SymbolLiteral)) and
result.getFieldName() = this.getName()

View File

@@ -137,16 +137,16 @@ private module Settings {
}
private class LiteralSetting extends Setting {
Literal valueLiteral;
ConstantValue value;
LiteralSetting() {
exists(DataFlow::LocalSourceNode lsn |
lsn.asExpr().getExpr() = valueLiteral and
lsn.asExpr().getConstantValue() = value and
lsn.flowsTo(this.getArgument(0))
)
}
string getValueText() { result = valueLiteral.getValueText() }
string getValueText() { result = value.toString() }
string getSettingString() { result = this.getMethodName() + this.getValueText() }
}
@@ -155,16 +155,16 @@ private module Settings {
* A node that sets a boolean value.
*/
class BooleanSetting extends LiteralSetting {
override BooleanLiteral valueLiteral;
override ConstantValue::ConstantBooleanValue value;
boolean getValue() { result = valueLiteral.getValue() }
boolean getValue() { result = value.getBoolean() }
}
/**
* A node that sets a Stringlike value.
*/
class StringlikeSetting extends LiteralSetting {
override StringlikeLiteral valueLiteral;
override ConstantValue::ConstantStringValue value;
}
/**
@@ -172,13 +172,13 @@ private module Settings {
*/
class NillableStringlikeSetting extends LiteralSetting {
NillableStringlikeSetting() {
valueLiteral instanceof StringlikeLiteral or
valueLiteral instanceof NilLiteral
value instanceof ConstantValue::ConstantStringValue or
value instanceof ConstantValue::ConstantNilValue
}
string getStringValue() { result = valueLiteral.(StringlikeLiteral).getValueText() }
string getStringValue() { result = value.getString() }
predicate isNilValue() { valueLiteral instanceof NilLiteral }
predicate isNilValue() { value.isNil() }
}
}

View File

@@ -484,7 +484,7 @@ private class ArrayIndex extends int {
module Array {
bindingset[arg]
private DataFlow::Content::KnownArrayElementContent getKnownArrayElementContent(Expr arg) {
result.getIndex() = arg.getValueText().toInt()
result.getIndex() = arg.getConstantValue().getInt()
}
bindingset[arg]
@@ -915,9 +915,9 @@ module Array {
private string getDigArg(MethodCall dig, int i) {
dig.getMethodName() = "dig" and
exists(Expr arg | arg = dig.getArgument(i) |
result = arg.getValueText().toInt().toString()
result = arg.getConstantValue().getInt().toString()
or
not exists(arg.getValueText()) and
not exists(arg.getConstantValue()) and
result = "?"
)
}
@@ -1271,7 +1271,7 @@ module Enumerable {
DropKnownSummary() {
this = "drop(" + i + ")" and
i = mc.getArgument(0).getValueText().toInt()
i = mc.getArgument(0).getConstantValue().getInt()
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
@@ -1291,7 +1291,7 @@ module Enumerable {
private class DropUnknownSummary extends DropSummary {
DropUnknownSummary() {
this = "drop(index)" and
not exists(mc.getArgument(0).getValueText().toInt())
not exists(mc.getArgument(0).getConstantValue().getInt())
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
@@ -1462,7 +1462,7 @@ module Enumerable {
private int n;
FirstArgKnownSummary() {
this = "first(" + n + ")" and n = mc.getArgument(0).getValueText().toInt()
this = "first(" + n + ")" and n = mc.getArgument(0).getConstantValue().getInt()
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
@@ -1484,7 +1484,7 @@ module Enumerable {
FirstArgUnknownSummary() {
this = "first(?)" and
mc.getNumberOfArguments() > 0 and
not exists(mc.getArgument(0).getValueText().toInt())
not exists(mc.getArgument(0).getConstantValue().getInt())
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {

View File

@@ -54,7 +54,7 @@ private class LibXmlRubyXmlParserCall extends XmlParserCall::Range, DataFlow::Ca
override predicate externalEntitiesEnabled() {
exists(Pair pair |
pair = this.getArgument(1).asExpr().getExpr().(HashLiteral).getAKeyValuePair() and
pair.getKey().(Literal).getValueText() = "options" and
pair.getKey().getConstantValue().isString("options") and
pair.getValue() =
[
trackEnableFeature(TNOENT()), trackEnableFeature(TDTDLOAD()),

View File

@@ -119,7 +119,7 @@ private predicate setsDefaultVerification(DataFlow::CallNode callNode, boolean v
private predicate isSslVerifyPeerLiteral(DataFlow::Node node) {
exists(DataFlow::LocalSourceNode literal |
literal.asExpr().getExpr().(SymbolLiteral).getValueText() = "ssl_verify_peer" and
literal.asExpr().getExpr().getConstantValue().isString("ssl_verify_peer") and
literal.flowsTo(node)
)
}

View File

@@ -90,7 +90,7 @@ private predicate isSslOptionsPairDisablingValidation(Pair p) {
/** Holds if `node` represents the symbol literal with the given `valueText`. */
private predicate isSymbolLiteral(DataFlow::Node node, string valueText) {
exists(DataFlow::LocalSourceNode literal |
literal.asExpr().getExpr().(SymbolLiteral).getValueText() = valueText and
literal.asExpr().getExpr().getConstantValue().isString(valueText) and
literal.flowsTo(node)
)
}

View File

@@ -72,7 +72,7 @@ class HttpartyRequest extends HTTP::Client::Request::Range {
/** Holds if `node` represents the symbol literal `verify` or `verify_peer`. */
private predicate isVerifyLiteral(DataFlow::Node node) {
exists(DataFlow::LocalSourceNode literal |
literal.asExpr().getExpr().(SymbolLiteral).getValueText() = ["verify", "verify_peer"] and
literal.asExpr().getExpr().getConstantValue().isString(["verify", "verify_peer"]) and
literal.flowsTo(node)
)
}

View File

@@ -111,7 +111,7 @@ private predicate isSslVerifyModeNonePair(Pair p) {
/** Holds if `node` can represent the symbol literal `:ssl_verify_mode`. */
private predicate isSslVerifyModeLiteral(DataFlow::Node node) {
exists(DataFlow::LocalSourceNode literal |
literal.asExpr().getExpr().(SymbolLiteral).getValueText() = "ssl_verify_mode" and
literal.asExpr().getExpr().getConstantValue().isString("ssl_verify_mode") and
literal.flowsTo(node)
)
}

View File

@@ -80,7 +80,7 @@ private predicate isVerifySslNonePair(Pair p) {
/** Holds if `node` can represent the symbol literal `:verify_ssl`. */
private predicate isSslVerifyModeLiteral(DataFlow::Node node) {
exists(DataFlow::LocalSourceNode literal |
literal.asExpr().getExpr().(SymbolLiteral).getValueText() = "verify_ssl" and
literal.asExpr().getExpr().getConstantValue().isString("verify_ssl") and
literal.flowsTo(node)
)
}

View File

@@ -62,7 +62,7 @@ private predicate isSslVerifyPeerFalsePair(Pair p) {
/** Holds if `node` represents the symbol literal `verify` or `verify_peer`. */
private predicate isSslVerifyPeerLiteral(DataFlow::Node node) {
exists(DataFlow::LocalSourceNode literal |
literal.asExpr().getExpr().(SymbolLiteral).getValueText() = "ssl_verifypeer" and
literal.asExpr().getExpr().getConstantValue().isString("ssl_verifypeer") and
literal.flowsTo(node)
)
}

View File

@@ -74,9 +74,9 @@ module UnsafeDeserialization {
}
private predicate isOjModePair(Pair p, string modeValue) {
p.getKey().getValueText() = "mode" and
p.getKey().getConstantValue().isString("mode") and
exists(DataFlow::LocalSourceNode symbolLiteral, DataFlow::Node value |
symbolLiteral.asExpr().getExpr().(SymbolLiteral).getValueText() = modeValue and
symbolLiteral.asExpr().getExpr().getConstantValue().isString(modeValue) and
symbolLiteral.flowsTo(value) and
value.asExpr().getExpr() = p.getValue()
)

View File

@@ -141,7 +141,7 @@ private module Shared {
exists(RenderCall call, Pair kvPair |
call.getLocals().getAKeyValuePair() = kvPair and
kvPair.getValue() = value and
kvPair.getKey().getValueText() = hashKey and
kvPair.getKey().getConstantValue().isString(hashKey) and
call.getTemplateFile() = erb
)
}
@@ -154,7 +154,7 @@ private module Shared {
argNode.asExpr() = refNode.getArgument(0) and
refNode.getReceiver().getExpr().(MethodCall).getMethodName() = "local_assigns" and
argNode.getALocalSource() = DataFlow::exprNode(strNode) and
strNode.getExpr().getValueText() = hashKey and
strNode.getExpr().getConstantValue().isString(hashKey) and
erb = refNode.getFile()
)
}

View File

@@ -203,7 +203,7 @@ class RegExp extends AST::RegExpLiteral {
}
/** Gets the text of this regex */
string getText() { result = this.getValueText() }
string getText() { result = this.getConstantValue().getString() }
string getChar(int i) { result = this.getText().charAt(i) }

View File

@@ -24,7 +24,7 @@ class EndCall extends MethodCall {
this.getNumberOfArguments() = 0
or
this.getNumberOfArguments() = 1 and
this.getArgument(0).(IntegerLiteral).getValueText() = "0"
this.getArgument(0).getConstantValue().isInt(0)
)
or
detect = "reverse_detect" and
@@ -33,7 +33,7 @@ class EndCall extends MethodCall {
this.getNumberOfArguments() = 0
or
this.getNumberOfArguments() = 1 and
this.getArgument(0).(UnaryMinusExpr).getOperand().(IntegerLiteral).getValueText() = "1"
this.getArgument(0).getConstantValue().isInt(-1)
)
}

View File

@@ -40,7 +40,10 @@ class PermissivePermissionsExpr extends Expr {
)
or
// adding/setting read or write permissions for all/group/other
this.(StringLiteral).getValueText().regexpMatch(".*[ago][^-=+]*[+=][xXst]*[rw].*")
this.(StringLiteral)
.getConstantValue()
.getString()
.regexpMatch(".*[ago][^-=+]*[+=][xXst]*[rw].*")
}
}

View File

@@ -18,10 +18,12 @@ import DataFlow::PathGraph
import codeql.ruby.TaintTracking
import codeql.ruby.controlflow.CfgNodes
private string getValueText(StringLiteral sl) { result = sl.getConstantValue().getString() }
bindingset[char, fraction]
predicate fewer_characters_than(StringLiteral str, string char, float fraction) {
exists(string text, int chars |
text = str.getValueText() and
text = getValueText(str) and
chars = count(int i | text.charAt(i) = char)
|
/* Allow one character */
@@ -35,17 +37,17 @@ predicate possible_reflective_name(string name) {
none()
}
int char_count(StringLiteral str) { result = count(string c | c = str.getValueText().charAt(_)) }
int char_count(StringLiteral str) { result = count(string c | c = getValueText(str).charAt(_)) }
predicate capitalized_word(StringLiteral str) { str.getValueText().regexpMatch("[A-Z][a-z]+") }
predicate capitalized_word(StringLiteral str) { getValueText(str).regexpMatch("[A-Z][a-z]+") }
predicate format_string(StringLiteral str) { str.getValueText().matches("%{%}%") }
predicate format_string(StringLiteral str) { getValueText(str).matches("%{%}%") }
predicate maybeCredential(Expr e) {
/* A string that is not too short and unlikely to be text or an identifier. */
exists(StringLiteral str | str = e |
/* At least 10 characters */
str.getValueText().length() > 9 and
getValueText(str).length() > 9 and
/* Not too much whitespace */
fewer_characters_than(str, " ", 0.05) and
/* or underscores */
@@ -53,9 +55,9 @@ predicate maybeCredential(Expr e) {
/* Not too repetitive */
exists(int chars | chars = char_count(str) |
chars > 15 or
chars * 3 > str.getValueText().length() * 2
chars * 3 > getValueText(str).length() * 2
) and
not possible_reflective_name(str.getValueText()) and
not possible_reflective_name(getValueText(str)) and
not capitalized_word(str) and
not format_string(str)
)
@@ -64,7 +66,7 @@ predicate maybeCredential(Expr e) {
exists(IntegerLiteral lit | lit = e |
not exists(lit.getValue()) and
/* Not a set of flags or round number */
not lit.getValueText().matches("%00%")
not lit.toString().matches("%00%")
)
}

View File

@@ -68,7 +68,7 @@ class DefaultTaintFlowConf extends TaintTracking::Configuration {
private string getSourceArgString(DataFlow::Node src) {
defaultSource(src) and
src.asExpr().getExpr().(MethodCall).getAnArgument().getValueText() = result
src.asExpr().getExpr().(MethodCall).getAnArgument().getConstantValue().toString() = result
}
class InlineFlowTest extends InlineExpectationsTest {

View File

@@ -214,7 +214,9 @@
| control/cases.rb:101:18:101:19 | 10 | 10 |
| control/cases.rb:102:6:102:9 | :foo | foo |
| control/cases.rb:103:6:103:15 | :"foo bar" | foo bar |
| control/cases.rb:104:6:104:7 | - ... | -5 |
| control/cases.rb:104:7:104:7 | 5 | 5 |
| control/cases.rb:104:11:104:13 | + ... | 10 |
| control/cases.rb:104:12:104:13 | 10 | 10 |
| control/cases.rb:105:7:105:7 | 1 | 1 |
| control/cases.rb:106:7:106:7 | 0 | 0 |
@@ -355,29 +357,27 @@
| gems/test.gemspec:9:3:9:12 | __synth__0 | https://github.com/github/codeql-ruby |
| gems/test.gemspec:9:19:9:57 | "https://github.com/github/cod..." | https://github.com/github/codeql-ruby |
| literals/literals.rb:2:1:2:3 | nil | nil |
| literals/literals.rb:3:1:3:3 | NIL | NIL |
| literals/literals.rb:3:1:3:3 | NIL | nil |
| literals/literals.rb:4:1:4:5 | false | false |
| literals/literals.rb:5:1:5:5 | FALSE | FALSE |
| literals/literals.rb:5:1:5:5 | FALSE | false |
| literals/literals.rb:6:1:6:4 | true | true |
| literals/literals.rb:7:1:7:4 | TRUE | TRUE |
| literals/literals.rb:7:1:7:4 | TRUE | true |
| literals/literals.rb:10:1:10:4 | 1234 | 1234 |
| literals/literals.rb:11:1:11:5 | 5_678 | 5_678 |
| literals/literals.rb:11:1:11:5 | 5_678 | 5678 |
| literals/literals.rb:12:1:12:1 | 0 | 0 |
| literals/literals.rb:13:1:13:5 | 0d900 | 0d900 |
| literals/literals.rb:16:1:16:6 | 0x1234 | 0x1234 |
| literals/literals.rb:17:1:17:10 | 0xdeadbeef | 0xdeadbeef |
| literals/literals.rb:18:1:18:11 | 0xF00D_face | 0xF00D_face |
| literals/literals.rb:21:1:21:4 | 0123 | 0123 |
| literals/literals.rb:22:1:22:5 | 0o234 | 0o234 |
| literals/literals.rb:23:1:23:6 | 0O45_6 | 0O45_6 |
| literals/literals.rb:26:1:26:10 | 0b10010100 | 0b10010100 |
| literals/literals.rb:27:1:27:11 | 0B011_01101 | 0B011_01101 |
| literals/literals.rb:13:1:13:5 | 0d900 | 0 |
| literals/literals.rb:16:1:16:6 | 0x1234 | 4660 |
| literals/literals.rb:21:1:21:4 | 0123 | 83 |
| literals/literals.rb:22:1:22:5 | 0o234 | 156 |
| literals/literals.rb:23:1:23:6 | 0O45_6 | 302 |
| literals/literals.rb:26:1:26:10 | 0b10010100 | 148 |
| literals/literals.rb:27:1:27:11 | 0B011_01101 | 109 |
| literals/literals.rb:30:1:30:5 | 12.34 | 12.34 |
| literals/literals.rb:31:1:31:7 | 1234e-2 | 1234e-2 |
| literals/literals.rb:32:1:32:7 | 1.234E1 | 1.234E1 |
| literals/literals.rb:35:1:35:3 | 23r | 23r |
| literals/literals.rb:36:1:36:5 | 9.85r | 9.85r |
| literals/literals.rb:39:1:39:2 | 2i | 2i |
| literals/literals.rb:31:1:31:7 | 1234e-2 | 12.34 |
| literals/literals.rb:32:1:32:7 | 1.234E1 | 12.34 |
| literals/literals.rb:35:1:35:3 | 23r | 23/1 |
| literals/literals.rb:36:1:36:5 | 9.85r | 985/100 |
| literals/literals.rb:39:1:39:2 | 2i | 0+2i |
| literals/literals.rb:46:1:46:2 | "" | |
| literals/literals.rb:47:1:47:2 | "" | |
| literals/literals.rb:48:1:48:7 | "hello" | hello |
@@ -633,7 +633,9 @@
| operations/operations.rb:20:5:20:5 | 0 | 0 |
| operations/operations.rb:23:2:23:2 | a | 0 |
| operations/operations.rb:24:5:24:5 | b | 0 |
| operations/operations.rb:25:1:25:3 | + ... | 14 |
| operations/operations.rb:25:2:25:3 | 14 | 14 |
| operations/operations.rb:26:1:26:2 | - ... | -7 |
| operations/operations.rb:26:2:26:2 | 7 | 7 |
| operations/operations.rb:27:2:27:2 | x | 0 |
| operations/operations.rb:28:10:28:12 | foo | 0 |
@@ -674,9 +676,9 @@
| operations/operations.rb:47:1:47:1 | y | 0 |
| operations/operations.rb:47:6:47:7 | 16 | 16 |
| operations/operations.rb:48:1:48:3 | foo | 0 |
| operations/operations.rb:48:7:48:10 | 0xff | 0xff |
| operations/operations.rb:48:7:48:10 | 0xff | 255 |
| operations/operations.rb:49:1:49:3 | bar | 0 |
| operations/operations.rb:49:7:49:10 | 0x02 | 0x02 |
| operations/operations.rb:49:7:49:10 | 0x02 | 2 |
| operations/operations.rb:50:1:50:3 | baz | 0 |
| operations/operations.rb:50:7:50:9 | qux | 0 |
| operations/operations.rb:53:1:53:1 | x | 0 |
@@ -724,7 +726,7 @@
| operations/operations.rb:82:8:82:8 | 3 | 3 |
| operations/operations.rb:83:9:83:12 | mask | 0 |
| operations/operations.rb:84:2:84:4 | bar | 0 |
| operations/operations.rb:84:9:84:12 | 0x01 | 0x01 |
| operations/operations.rb:84:9:84:12 | 0x01 | 1 |
| operations/operations.rb:85:2:85:4 | baz | 0 |
| operations/operations.rb:85:9:85:11 | qux | 0 |
| operations/operations.rb:88:8:88:8 | 1 | 1 |

View File

@@ -1,4 +1,4 @@
import ruby
from Expr e
select e, e.getValueText()
select e, e.getConstantValue()

View File

@@ -1,28 +1,28 @@
allLiterals
| literals.rb:2:1:2:3 | nil | NilLiteral | nil |
| literals.rb:3:1:3:3 | NIL | NilLiteral | NIL |
| literals.rb:3:1:3:3 | NIL | NilLiteral | nil |
| literals.rb:4:1:4:5 | false | BooleanLiteral | false |
| literals.rb:5:1:5:5 | FALSE | BooleanLiteral | FALSE |
| literals.rb:5:1:5:5 | FALSE | BooleanLiteral | false |
| literals.rb:6:1:6:4 | true | BooleanLiteral | true |
| literals.rb:7:1:7:4 | TRUE | BooleanLiteral | TRUE |
| literals.rb:7:1:7:4 | TRUE | BooleanLiteral | true |
| literals.rb:10:1:10:4 | 1234 | IntegerLiteral | 1234 |
| literals.rb:11:1:11:5 | 5_678 | IntegerLiteral | 5_678 |
| literals.rb:11:1:11:5 | 5_678 | IntegerLiteral | 5678 |
| literals.rb:12:1:12:1 | 0 | IntegerLiteral | 0 |
| literals.rb:13:1:13:5 | 0d900 | IntegerLiteral | 0d900 |
| literals.rb:16:1:16:6 | 0x1234 | IntegerLiteral | 0x1234 |
| literals.rb:17:1:17:10 | 0xdeadbeef | IntegerLiteral | 0xdeadbeef |
| literals.rb:18:1:18:11 | 0xF00D_face | IntegerLiteral | 0xF00D_face |
| literals.rb:21:1:21:4 | 0123 | IntegerLiteral | 0123 |
| literals.rb:22:1:22:5 | 0o234 | IntegerLiteral | 0o234 |
| literals.rb:23:1:23:6 | 0O45_6 | IntegerLiteral | 0O45_6 |
| literals.rb:26:1:26:10 | 0b10010100 | IntegerLiteral | 0b10010100 |
| literals.rb:27:1:27:11 | 0B011_01101 | IntegerLiteral | 0B011_01101 |
| literals.rb:13:1:13:5 | 0d900 | IntegerLiteral | 0 |
| literals.rb:16:1:16:6 | 0x1234 | IntegerLiteral | 4660 |
| literals.rb:17:1:17:10 | 0xdeadbeef | IntegerLiteral | <none> |
| literals.rb:18:1:18:11 | 0xF00D_face | IntegerLiteral | <none> |
| literals.rb:21:1:21:4 | 0123 | IntegerLiteral | 83 |
| literals.rb:22:1:22:5 | 0o234 | IntegerLiteral | 156 |
| literals.rb:23:1:23:6 | 0O45_6 | IntegerLiteral | 302 |
| literals.rb:26:1:26:10 | 0b10010100 | IntegerLiteral | 148 |
| literals.rb:27:1:27:11 | 0B011_01101 | IntegerLiteral | 109 |
| literals.rb:30:1:30:5 | 12.34 | FloatLiteral | 12.34 |
| literals.rb:31:1:31:7 | 1234e-2 | FloatLiteral | 1234e-2 |
| literals.rb:32:1:32:7 | 1.234E1 | FloatLiteral | 1.234E1 |
| literals.rb:35:1:35:3 | 23r | RationalLiteral | 23r |
| literals.rb:36:1:36:5 | 9.85r | RationalLiteral | 9.85r |
| literals.rb:39:1:39:2 | 2i | ComplexLiteral | 2i |
| literals.rb:31:1:31:7 | 1234e-2 | FloatLiteral | 12.34 |
| literals.rb:32:1:32:7 | 1.234E1 | FloatLiteral | 12.34 |
| literals.rb:35:1:35:3 | 23r | RationalLiteral | 23/1 |
| literals.rb:36:1:36:5 | 9.85r | RationalLiteral | 985/100 |
| literals.rb:39:1:39:2 | 2i | ComplexLiteral | 0+2i |
| literals.rb:46:1:46:2 | "" | StringLiteral | |
| literals.rb:47:1:47:2 | "" | StringLiteral | |
| literals.rb:48:1:48:7 | "hello" | StringLiteral | hello |
@@ -735,23 +735,23 @@ exclusiveRangeLiterals
| literals.rb:122:2:122:7 | _ ... _ |
numericLiterals
| literals.rb:10:1:10:4 | 1234 | IntegerLiteral | 1234 |
| literals.rb:11:1:11:5 | 5_678 | IntegerLiteral | 5_678 |
| literals.rb:11:1:11:5 | 5_678 | IntegerLiteral | 5678 |
| literals.rb:12:1:12:1 | 0 | IntegerLiteral | 0 |
| literals.rb:13:1:13:5 | 0d900 | IntegerLiteral | 0d900 |
| literals.rb:16:1:16:6 | 0x1234 | IntegerLiteral | 0x1234 |
| literals.rb:17:1:17:10 | 0xdeadbeef | IntegerLiteral | 0xdeadbeef |
| literals.rb:18:1:18:11 | 0xF00D_face | IntegerLiteral | 0xF00D_face |
| literals.rb:21:1:21:4 | 0123 | IntegerLiteral | 0123 |
| literals.rb:22:1:22:5 | 0o234 | IntegerLiteral | 0o234 |
| literals.rb:23:1:23:6 | 0O45_6 | IntegerLiteral | 0O45_6 |
| literals.rb:26:1:26:10 | 0b10010100 | IntegerLiteral | 0b10010100 |
| literals.rb:27:1:27:11 | 0B011_01101 | IntegerLiteral | 0B011_01101 |
| literals.rb:13:1:13:5 | 0d900 | IntegerLiteral | 0 |
| literals.rb:16:1:16:6 | 0x1234 | IntegerLiteral | 4660 |
| literals.rb:17:1:17:10 | 0xdeadbeef | IntegerLiteral | <none> |
| literals.rb:18:1:18:11 | 0xF00D_face | IntegerLiteral | <none> |
| literals.rb:21:1:21:4 | 0123 | IntegerLiteral | 83 |
| literals.rb:22:1:22:5 | 0o234 | IntegerLiteral | 156 |
| literals.rb:23:1:23:6 | 0O45_6 | IntegerLiteral | 302 |
| literals.rb:26:1:26:10 | 0b10010100 | IntegerLiteral | 148 |
| literals.rb:27:1:27:11 | 0B011_01101 | IntegerLiteral | 109 |
| literals.rb:30:1:30:5 | 12.34 | FloatLiteral | 12.34 |
| literals.rb:31:1:31:7 | 1234e-2 | FloatLiteral | 1234e-2 |
| literals.rb:32:1:32:7 | 1.234E1 | FloatLiteral | 1.234E1 |
| literals.rb:35:1:35:3 | 23r | RationalLiteral | 23r |
| literals.rb:36:1:36:5 | 9.85r | RationalLiteral | 9.85r |
| literals.rb:39:1:39:2 | 2i | ComplexLiteral | 2i |
| literals.rb:31:1:31:7 | 1234e-2 | FloatLiteral | 12.34 |
| literals.rb:32:1:32:7 | 1.234E1 | FloatLiteral | 12.34 |
| literals.rb:35:1:35:3 | 23r | RationalLiteral | 23/1 |
| literals.rb:36:1:36:5 | 9.85r | RationalLiteral | 985/100 |
| literals.rb:39:1:39:2 | 2i | ComplexLiteral | 0+2i |
| literals.rb:58:13:58:13 | 2 | IntegerLiteral | 2 |
| literals.rb:58:17:58:17 | 2 | IntegerLiteral | 2 |
| literals.rb:59:15:59:15 | 3 | IntegerLiteral | 3 |
@@ -804,17 +804,17 @@ numericLiterals
| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
integerLiterals
| literals.rb:10:1:10:4 | 1234 | IntegerLiteral | 1234 |
| literals.rb:11:1:11:5 | 5_678 | IntegerLiteral | 5_678 |
| literals.rb:11:1:11:5 | 5_678 | IntegerLiteral | 5678 |
| literals.rb:12:1:12:1 | 0 | IntegerLiteral | 0 |
| literals.rb:13:1:13:5 | 0d900 | IntegerLiteral | 0d900 |
| literals.rb:16:1:16:6 | 0x1234 | IntegerLiteral | 0x1234 |
| literals.rb:17:1:17:10 | 0xdeadbeef | IntegerLiteral | 0xdeadbeef |
| literals.rb:18:1:18:11 | 0xF00D_face | IntegerLiteral | 0xF00D_face |
| literals.rb:21:1:21:4 | 0123 | IntegerLiteral | 0123 |
| literals.rb:22:1:22:5 | 0o234 | IntegerLiteral | 0o234 |
| literals.rb:23:1:23:6 | 0O45_6 | IntegerLiteral | 0O45_6 |
| literals.rb:26:1:26:10 | 0b10010100 | IntegerLiteral | 0b10010100 |
| literals.rb:27:1:27:11 | 0B011_01101 | IntegerLiteral | 0B011_01101 |
| literals.rb:13:1:13:5 | 0d900 | IntegerLiteral | 0 |
| literals.rb:16:1:16:6 | 0x1234 | IntegerLiteral | 4660 |
| literals.rb:17:1:17:10 | 0xdeadbeef | IntegerLiteral | <none> |
| literals.rb:18:1:18:11 | 0xF00D_face | IntegerLiteral | <none> |
| literals.rb:21:1:21:4 | 0123 | IntegerLiteral | 83 |
| literals.rb:22:1:22:5 | 0o234 | IntegerLiteral | 156 |
| literals.rb:23:1:23:6 | 0O45_6 | IntegerLiteral | 302 |
| literals.rb:26:1:26:10 | 0b10010100 | IntegerLiteral | 148 |
| literals.rb:27:1:27:11 | 0B011_01101 | IntegerLiteral | 109 |
| literals.rb:58:13:58:13 | 2 | IntegerLiteral | 2 |
| literals.rb:58:17:58:17 | 2 | IntegerLiteral | 2 |
| literals.rb:59:15:59:15 | 3 | IntegerLiteral | 3 |
@@ -867,10 +867,10 @@ integerLiterals
| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
floatLiterals
| literals.rb:30:1:30:5 | 12.34 | FloatLiteral | 12.34 |
| literals.rb:31:1:31:7 | 1234e-2 | FloatLiteral | 1234e-2 |
| literals.rb:32:1:32:7 | 1.234E1 | FloatLiteral | 1.234E1 |
| literals.rb:31:1:31:7 | 1234e-2 | FloatLiteral | 12.34 |
| literals.rb:32:1:32:7 | 1.234E1 | FloatLiteral | 12.34 |
rationalLiterals
| literals.rb:35:1:35:3 | 23r | RationalLiteral | 23r |
| literals.rb:36:1:36:5 | 9.85r | RationalLiteral | 9.85r |
| literals.rb:35:1:35:3 | 23r | RationalLiteral | 23/1 |
| literals.rb:36:1:36:5 | 9.85r | RationalLiteral | 985/100 |
complexLiterals
| literals.rb:39:1:39:2 | 2i | ComplexLiteral | 2i |
| literals.rb:39:1:39:2 | 2i | ComplexLiteral | 0+2i |

View File

@@ -3,16 +3,16 @@ import ruby
query predicate allLiterals(Literal l, string pClass, string valueText) {
pClass = l.getAPrimaryQlClass() and
(
valueText = l.getValueText()
valueText = l.getConstantValue().toString()
or
not exists(l.getValueText()) and valueText = "<none>"
not exists(l.getConstantValue()) and valueText = "<none>"
)
}
query predicate stringlikeLiterals(StringlikeLiteral l, string valueText) {
valueText = l.getValueText()
valueText = l.getConstantValue().toString()
or
not exists(l.getValueText()) and valueText = "<none>"
not exists(l.getConstantValue()) and valueText = "<none>"
}
query predicate stringLiterals(StringLiteral l, string valueText) {

View File

@@ -1,9 +1,9 @@
import ruby
private string getValueText(MethodName m) {
result = m.getValueText()
result = m.getConstantValue().getString()
or
not exists(m.getValueText()) and result = "(none)"
not exists(m.getConstantValue()) and result = "(none)"
}
query predicate undef(UndefStmt u, int i, MethodName m, string name, string pClass) {

View File

@@ -10,7 +10,7 @@ class Conf extends DataFlow::Configuration {
Conf() { this = "Conf" }
override predicate isSource(DataFlow::Node src) {
src.asExpr().getExpr().(StringLiteral).getValueText() = "taint"
src.asExpr().getExpr().(StringLiteral).getConstantValue().isString("taint")
}
override predicate isSink(DataFlow::Node sink) {

View File

@@ -67,7 +67,7 @@ class Conf extends TaintTracking::Configuration {
Conf() { this = "FlowSummaries" }
override predicate isSource(DataFlow::Node src) {
src.asExpr().getExpr().(StringLiteral).getValueText() = "taint"
src.asExpr().getExpr().(StringLiteral).getConstantValue().isString("taint")
}
override predicate isSink(DataFlow::Node sink) {