Merge branch 'main' into refacReDoS

This commit is contained in:
erik-krogh
2022-08-12 20:28:30 +02:00
502 changed files with 42258 additions and 31255 deletions

View File

@@ -21,7 +21,7 @@ class File extends Container, @file {
/** Whether this file is a source code file. */
predicate fromSource() {
/* If we start to analyse .pyc files, then this will have to change. */
/* If we start to analyze .pyc files, then this will have to change. */
any()
}

View File

@@ -2,7 +2,7 @@
* Helper file that imports all framework modeling.
*/
// If you add modeling of a new framework/library, remember to add it it to the docs in
// If you add modeling of a new framework/library, remember to add it to the docs in
// `docs/codeql/support/reusables/frameworks.rst`
private import semmle.python.frameworks.Aioch
private import semmle.python.frameworks.Aiohttp

View File

@@ -71,7 +71,7 @@ deprecated Node importNode(string name) {
// ```
//
// Where `foo_module_tracker` is a type tracker that tracks references to the `foo` module.
// Because named imports are modelled as `AttrRead`s, the statement `from foo import bar as baz`
// Because named imports are modeled as `AttrRead`s, the statement `from foo import bar as baz`
// is interpreted as if it was an assignment `baz = foo.bar`, which means `baz` gets tracked as a
// reference to `foo.bar`, as desired.
exists(ImportExpr imp_expr |

View File

@@ -333,7 +333,7 @@ abstract class Sanitizer extends string {
/** Holds if `taint` cannot flow through `node`. */
predicate sanitizingNode(TaintKind taint, ControlFlowNode node) { none() }
/** Holds if `call` removes removes the `taint` */
/** Holds if `call` removes the `taint` */
predicate sanitizingCall(TaintKind taint, FunctionObject callee) { none() }
/** Holds if `test` shows value to be untainted with `taint` */

View File

@@ -212,8 +212,8 @@ class EssaEdgeRefinement extends EssaDefinition, TEssaEdgeDefinition {
/** Gets the SSA variable to which this refinement applies. */
EssaVariable getInput() {
exists(SsaSourceVariable var, EssaDefinition def |
var = this.getSourceVariable() and
var = def.getSourceVariable() and
pragma[only_bind_into](var) = this.getSourceVariable() and
pragma[only_bind_into](var) = def.getSourceVariable() and
def.reachesEndOfBlock(this.getPredecessor()) and
result.getDefinition() = def
)

View File

@@ -42,7 +42,7 @@ private module NotExposed {
// Implementation below
// ---------------------------------------------------------------------------
//
// We are looking to find all subclassed of the already modelled classes, and ideally
// We are looking to find all subclassed of the already modeled classes, and ideally
// we would identify an `API::Node` for each (then `toString` would give the API
// path).
//

View File

@@ -273,6 +273,41 @@ predicate builtin_name_points_to(string name, Object value, ClassObject cls) {
value = Object::builtin(name) and cls.asBuiltin() = value.asBuiltin().getClass()
}
pragma[nomagic]
private predicate essa_var_scope(SsaSourceVariable var, Scope pred_scope, EssaVariable pred_var) {
BaseFlow::reaches_exit(pred_var) and
pred_var.getScope() = pred_scope and
var = pred_var.getSourceVariable()
}
pragma[nomagic]
private predicate scope_entry_def_scope(
SsaSourceVariable var, Scope succ_scope, ScopeEntryDefinition succ_def
) {
var = succ_def.getSourceVariable() and
succ_def.getScope() = succ_scope
}
pragma[nomagic]
private predicate step_through_init(Scope succ_scope, Scope pred_scope, Scope init) {
init.getName() = "__init__" and
init.precedes(succ_scope) and
pred_scope.precedes(init)
}
pragma[nomagic]
private predicate scope_entry_value_transfer_through_init(
EssaVariable pred_var, Scope pred_scope, ScopeEntryDefinition succ_def, Scope succ_scope
) {
exists(SsaSourceVariable var, Scope init |
var instanceof GlobalVariable and
essa_var_scope(var, pragma[only_bind_into](pred_scope), pred_var) and
scope_entry_def_scope(var, succ_scope, succ_def) and
step_through_init(succ_scope, pragma[only_bind_into](pred_scope), init) and
not var.(Variable).getAStore().getScope() = init
)
}
module BaseFlow {
predicate reaches_exit(EssaVariable var) { var.getAUse() = var.getScope().getANormalExit() }
@@ -283,27 +318,15 @@ module BaseFlow {
) {
Stages::DataFlow::ref() and
exists(SsaSourceVariable var |
reaches_exit(pred_var) and
pred_var.getScope() = pred_scope and
var = pred_var.getSourceVariable() and
var = succ_def.getSourceVariable() and
succ_def.getScope() = succ_scope
essa_var_scope(var, pred_scope, pred_var) and
scope_entry_def_scope(var, succ_scope, succ_def)
|
pred_scope.precedes(succ_scope)
or
/*
* If an `__init__` method does not modify the global variable, then
* we can skip it and take the value directly from the module.
*/
exists(Scope init |
init.getName() = "__init__" and
init.precedes(succ_scope) and
pred_scope.precedes(init) and
not var.(Variable).getAStore().getScope() = init and
var instanceof GlobalVariable
)
)
or
// If an `__init__` method does not modify the global variable, then
// we can skip it and take the value directly from the module.
scope_entry_value_transfer_through_init(pred_var, pred_scope, succ_def, succ_scope)
}
}

View File

@@ -23,13 +23,8 @@ private int max_context_cost() {
}
private int syntactic_call_count(Scope s) {
exists(Function f | f = s and f.getName() != "__init__" |
result =
count(CallNode call |
call.getFunction().(NameNode).getId() = f.getName()
or
call.getFunction().(AttrNode).getName() = f.getName()
)
exists(Function f, string name | f = s and name = f.getName() and name != "__init__" |
result = count(function_call(name)) + count(method_call(name))
)
or
s.getName() = "__init__" and result = 1
@@ -37,6 +32,12 @@ private int syntactic_call_count(Scope s) {
not s instanceof Function and result = 0
}
pragma[nomagic]
private CallNode function_call(string name) { result.getFunction().(NameNode).getId() = name }
pragma[nomagic]
private CallNode method_call(string name) { result.getFunction().(AttrNode).getName() = name }
private int incoming_call_cost(Scope s) {
/*
* Syntactic call count will often be a considerable overestimate

View File

@@ -35,7 +35,7 @@ private import semmle.python.objects.ObjectInternal
// functionality into `BuiltinFunctionValue` and `BuiltinMethodValue`, but will
// probably require some more work: for this query, it's totally ok to use
// `builtins.open` for the code `open(f)`, but well, it requires a bit of thinking to
// figure out if that is desireable in general. I simply skipped a corner here!
// figure out if that is desirable in general. I simply skipped a corner here!
// 4. TaintTrackingPrivate: Nothing else gives us access to `defaultAdditionalTaintStep` :(
/**
* A callable that is considered a "safe" external API from a security perspective.