mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
Ruby: tests, patterns, fix erb flow
This commit is contained in:
@@ -8,13 +8,13 @@ private import codeql.ruby.dataflow.FlowSummary
|
||||
|
||||
/** Provides modeling for the Sinatra library. */
|
||||
module Sinatra {
|
||||
private class App extends DataFlow::ClassNode {
|
||||
class App extends DataFlow::ClassNode {
|
||||
App() { this = DataFlow::getConstant("Sinatra").getConstant("Base").getADescendentModule() }
|
||||
|
||||
Route getRoute() { result.getApp() = this }
|
||||
Route getARoute() { result.getApp() = this }
|
||||
}
|
||||
|
||||
private class Route extends DataFlow::CallNode {
|
||||
class Route extends DataFlow::CallNode {
|
||||
private App app;
|
||||
|
||||
Route() {
|
||||
@@ -44,7 +44,7 @@ module Sinatra {
|
||||
}
|
||||
}
|
||||
|
||||
private class ErbCall extends DataFlow::CallNode {
|
||||
class ErbCall extends DataFlow::CallNode {
|
||||
private Route route;
|
||||
|
||||
ErbCall() {
|
||||
@@ -52,14 +52,18 @@ module Sinatra {
|
||||
this.getMethodName() = "erb"
|
||||
}
|
||||
|
||||
ErbFile getTemplateFile() {
|
||||
result.getTemplateName() =
|
||||
this.getArgument(0).asExpr().getConstantValue().getStringlikeValue() and
|
||||
result.getRelativePath().matches("%views/%")
|
||||
}
|
||||
/**
|
||||
* Gets the template file corresponding to this call.
|
||||
*/
|
||||
ErbFile getTemplateFile() { result = getTemplateFile(this.asExpr().getExpr()) }
|
||||
}
|
||||
|
||||
ErbFile getTemplateFile(MethodCall erbCall) {
|
||||
/**
|
||||
* Gets the template file referred to by `erbCall`.
|
||||
* This works on the AST level to avoid non-monotonic reecursion in `ErbLocalsHashSyntheticGlobal`.
|
||||
*/
|
||||
private ErbFile getTemplateFile(MethodCall erbCall) {
|
||||
erbCall.getMethodName() = "erb" and
|
||||
result.getTemplateName() = erbCall.getArgument(0).getConstantValue().getStringlikeValue() and
|
||||
result.getRelativePath().matches("%views/%")
|
||||
}
|
||||
@@ -73,7 +77,7 @@ module Sinatra {
|
||||
loc.getEndLine() + ":" + loc.getEndColumn()
|
||||
}
|
||||
|
||||
private class ErbLocalsHashSyntheticGlobal extends SummaryComponent::SyntheticGlobal {
|
||||
class ErbLocalsHashSyntheticGlobal extends SummaryComponent::SyntheticGlobal {
|
||||
private string id;
|
||||
private MethodCall erbCall;
|
||||
private ErbFile erbFile;
|
||||
@@ -98,7 +102,9 @@ module Sinatra {
|
||||
override MethodCall getACall() { result = any(ErbCall c).asExpr().getExpr() }
|
||||
|
||||
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[2]" and output = "SyntheticGlobal[" + global + "]" and preservesValue = true
|
||||
input = "Argument[locals:]" and
|
||||
output = "SyntheticGlobal[" + global + "]" and
|
||||
preservesValue = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,4 +130,43 @@ module Sinatra {
|
||||
preservesValue = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters are run before or after the route handler. They can modify the
|
||||
* request and response, and share instance variables with the route handler.
|
||||
*/
|
||||
class Filter extends DataFlow::CallNode {
|
||||
private App app;
|
||||
|
||||
Filter() { this = app.getAModuleLevelCall(["before", "after"]) }
|
||||
|
||||
/**
|
||||
* Gets the pattern which constrains this route, if any. In the example below, the pattern is `/protected/*`.
|
||||
* Patterns are typically given as strings, and are interpreted by the `mustermann` gem (they are not regular expressions).
|
||||
* ```rb
|
||||
* before '/protected/*' do
|
||||
* authenticate!
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
DataFlow::ExprNode getPattern() { result = this.getArgument(0) }
|
||||
|
||||
/**
|
||||
* Holds if this filter has a pattern.
|
||||
*/
|
||||
predicate hasPattern() { exists(this.getPattern()) }
|
||||
|
||||
/**
|
||||
* Gets the body of this filter.
|
||||
*/
|
||||
DataFlow::BlockNode getBody() { result = this.getBlock() }
|
||||
}
|
||||
|
||||
class BeforeFilter extends Filter {
|
||||
BeforeFilter() { this.getMethodName() = "before" }
|
||||
}
|
||||
|
||||
class AfterFilter extends Filter {
|
||||
AfterFilter() { this.getMethodName() = "after" }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user