mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
Merge pull request #10517 from hvitved/ruby/regexp-debug
Ruby: Add query for debugging regexp flow
This commit is contained in:
@@ -7,11 +7,10 @@
|
||||
|
||||
import regexp.RegExpTreeView // re-export
|
||||
private import regexp.internal.ParseRegExp
|
||||
private import codeql.ruby.ast.Literal as AST
|
||||
private import regexp.internal.RegExpConfiguration
|
||||
private import codeql.ruby.ast.Literal as Ast
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.controlflow.CfgNodes
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.dataflow.internal.tainttrackingforlibraries.TaintTrackingImpl
|
||||
|
||||
/**
|
||||
* Provides utility predicates related to regular expressions.
|
||||
@@ -47,7 +46,7 @@ abstract class RegExpPatternSource extends DataFlow::Node {
|
||||
* A regular expression literal, viewed as the pattern source for itself.
|
||||
*/
|
||||
private class RegExpLiteralPatternSource extends RegExpPatternSource {
|
||||
private AST::RegExpLiteral astNode;
|
||||
private Ast::RegExpLiteral astNode;
|
||||
|
||||
RegExpLiteralPatternSource() { astNode = this.asExpr().getExpr() }
|
||||
|
||||
@@ -70,7 +69,7 @@ private class StringRegExpPatternSource extends RegExpPatternSource {
|
||||
override RegExpTerm getRegExpTerm() { result.getRegExp() = this.asExpr().getExpr() }
|
||||
}
|
||||
|
||||
private class RegExpLiteralRegExp extends RegExp, AST::RegExpLiteral {
|
||||
private class RegExpLiteralRegExp extends RegExp, Ast::RegExpLiteral {
|
||||
override predicate isDotAll() { this.hasMultilineFlag() }
|
||||
|
||||
override predicate isIgnoreCase() { this.hasCaseInsensitiveFlag() }
|
||||
@@ -115,32 +114,7 @@ class StdLibRegExpInterpretation extends RegExpInterpretation::Range {
|
||||
mce.getMethodName() = ["match", "match?"] and
|
||||
this = mce.getArgument(0) and
|
||||
// exclude https://ruby-doc.org/core-2.4.0/Regexp.html#method-i-match
|
||||
not mce.getReceiver().asExpr().getExpr() instanceof AST::RegExpLiteral
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class RegExpConfiguration extends Configuration {
|
||||
RegExpConfiguration() { this = "RegExpConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr() =
|
||||
any(ExprCfgNode e |
|
||||
e.getConstantValue().isString(_) and
|
||||
not e instanceof ExprNodes::VariableReadAccessCfgNode and
|
||||
not e instanceof ExprNodes::ConstantReadAccessCfgNode
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof RegExpInterpretation::Range }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
// stop flow if `node` is receiver of
|
||||
// https://ruby-doc.org/core-2.4.0/String.html#method-i-match
|
||||
exists(DataFlow::CallNode mce |
|
||||
mce.getMethodName() = ["match", "match?"] and
|
||||
node = mce.getReceiver() and
|
||||
mce.getArgument(0).asExpr().getExpr() instanceof AST::RegExpLiteral
|
||||
not mce.getReceiver().asExpr().getExpr() instanceof Ast::RegExpLiteral
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* @description Used to debug the discovery of regexp literals.
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import RegExpConfiguration
|
||||
import codeql.ruby.dataflow.internal.DataFlowImplForLibraries
|
||||
import PathGraph
|
||||
|
||||
from RegExpConfiguration c, PathNode source, PathNode sink
|
||||
where c.hasFlowPath(source, sink)
|
||||
select source.getNode(), source, sink, source.toString()
|
||||
@@ -0,0 +1,30 @@
|
||||
private import codeql.ruby.Regexp
|
||||
private import codeql.ruby.ast.Literal as Ast
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.controlflow.CfgNodes
|
||||
private import codeql.ruby.dataflow.internal.tainttrackingforlibraries.TaintTrackingImpl
|
||||
|
||||
class RegExpConfiguration extends Configuration {
|
||||
RegExpConfiguration() { this = "RegExpConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr() =
|
||||
any(ExprCfgNode e |
|
||||
e.getConstantValue().isString(_) and
|
||||
not e instanceof ExprNodes::VariableReadAccessCfgNode and
|
||||
not e instanceof ExprNodes::ConstantReadAccessCfgNode
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof RegExpInterpretation::Range }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
// stop flow if `node` is receiver of
|
||||
// https://ruby-doc.org/core-2.4.0/String.html#method-i-match
|
||||
exists(DataFlow::CallNode mce |
|
||||
mce.getMethodName() = ["match", "match?"] and
|
||||
node = mce.getReceiver() and
|
||||
mce.getArgument(0).asExpr().getExpr() instanceof Ast::RegExpLiteral
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user