mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Ruby: Replace getValueText with getConstantValue
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
29
ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll
Normal file
29
ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll
Normal 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() }
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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].*")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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%")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ruby
|
||||
|
||||
from Expr e
|
||||
select e, e.getValueText()
|
||||
select e, e.getConstantValue()
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user