mirror of
https://github.com/github/codeql.git
synced 2026-05-05 13:45:19 +02:00
Include simple interpolations in getValueText
When calculating `StringlikeLiteral.getValueText`, include results from
interpolations where we can determine their string value. For example:
b = "b" # local variable
D = "d" # constant
"a#{b}c" # getValueText() = "abc"
"a#{b}c{D}" # getValueText() = "abcd"
/#a#{b}c{D}/ # getValueText() = "abcd"
This commit is contained in:
committed by
Harry Maclean
parent
3df3fb092b
commit
32c93e70e2
@@ -3,6 +3,7 @@ private import codeql.ruby.security.performance.RegExpTreeView as RETV
|
||||
private import internal.AST
|
||||
private import internal.Scope
|
||||
private import internal.TreeSitter
|
||||
private import codeql.ruby.controlflow.CfgNodes
|
||||
|
||||
/**
|
||||
* A literal.
|
||||
@@ -411,14 +412,14 @@ class StringlikeLiteral extends Literal, TStringlikeLiteral {
|
||||
}
|
||||
|
||||
override string getValueText() {
|
||||
// 0 components should result in the empty string
|
||||
// if there are any interpolations, there should be no result
|
||||
// otherwise, concatenate all the components
|
||||
forall(StringComponent c | c = this.getComponent(_) |
|
||||
not c instanceof StringInterpolationComponent
|
||||
) and
|
||||
result =
|
||||
concat(StringComponent c, int i | c = this.getComponent(i) | c.getValueText() order by i)
|
||||
or
|
||||
exists(this.getComponent(_)) and
|
||||
result = this.getAControlFlowNode().(ExprNodes::StringlikeLiteralCfgNode).getValueText()
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
|
||||
@@ -128,6 +128,8 @@ class ReturningCfgNode extends AstCfgNode {
|
||||
/** A control-flow node that wraps a `StringComponent` AST expression. */
|
||||
class StringComponentCfgNode extends AstCfgNode {
|
||||
StringComponentCfgNode() { this.getNode() instanceof StringComponent }
|
||||
|
||||
string getValueText() { result = this.getNode().(StringComponent).getValueText() }
|
||||
}
|
||||
|
||||
private Expr desugar(Expr n) {
|
||||
@@ -463,8 +465,13 @@ module ExprNodes {
|
||||
}
|
||||
|
||||
/** A control-flow node that wraps a `StringInterpolationComponent` AST expression. */
|
||||
class StringInterpolationComponentCfgNode extends StmtSequenceCfgNode {
|
||||
class StringInterpolationComponentCfgNode extends StringComponentCfgNode, StmtSequenceCfgNode {
|
||||
StringInterpolationComponentCfgNode() { this.getNode() instanceof StringInterpolationComponent }
|
||||
|
||||
// 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() }
|
||||
}
|
||||
|
||||
private class StringlikeLiteralChildMapping extends ExprChildMapping, StringlikeLiteral {
|
||||
@@ -477,8 +484,36 @@ module ExprNodes {
|
||||
|
||||
final override StringlikeLiteral getExpr() { result = super.getExpr() }
|
||||
|
||||
/** Gets the `n`th component of this `StringlikeLiteral` */
|
||||
StringComponentCfgNode getComponent(int n) { result.getNode() = e.getComponent(n) }
|
||||
|
||||
/** Gets a component of this `StringlikeLiteral` */
|
||||
StringComponentCfgNode getAComponent() { e.hasCfgChild(e.getComponent(_), this, result) }
|
||||
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 = e.getValueText()
|
||||
or
|
||||
result =
|
||||
concat(StringComponent c, int i |
|
||||
c = e.getComponent(i)
|
||||
|
|
||||
getComponentValueText(c) order by i
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `ValueText()` of a `StringComponent`.
|
||||
* If the component has a CFG node, defer to that (in order to resolve variables in interpolations).
|
||||
* Otherwise, defer to the AST node.
|
||||
*/
|
||||
private string getComponentValueText(StringComponent c) {
|
||||
exists(StringComponentCfgNode n | n.getNode() = c | result = n.getValueText())
|
||||
or
|
||||
not exists(StringComponentCfgNode n | n.getNode() = c) and result = c.getValueText()
|
||||
}
|
||||
}
|
||||
|
||||
/** A control-flow node that wraps a `StringLiteral` AST expression. */
|
||||
|
||||
Reference in New Issue
Block a user