Skip to content

Commit

Permalink
Python: Address review comments
Browse files Browse the repository at this point in the history
Renames the methods to include the word `Positional`, and adds
documentation for the behaviour of `getMaxPositionalArguments` when the
function in question has a `*varargs` parameter (and hence no upper
limit on the number of arguments).
  • Loading branch information
tausbn committed Mar 4, 2025
1 parent 83cdcdb commit 11e6194
Showing 3 changed files with 28 additions and 18 deletions.
12 changes: 9 additions & 3 deletions python/ql/lib/semmle/python/Function.qll
Original file line number Diff line number Diff line change
@@ -165,12 +165,18 @@ class Function extends Function_, Scope, AstNode {
}

/** Gets the minimum number of positional arguments that can be correctly passed to this function. */
int getMinArguments() {
int getMinPositionalArguments() {
result = count(this.getAnArg()) - count(this.getDefinition().getArgs().getADefault())
}

/** Gets the maximum number of positional arguments that can be correctly passed to this function. */
int getMaxArguments() {
/**
* Gets the maximum number of positional arguments that can be correctly passed to this function.
*
* If the function has a `*vararg` parameter, there is no upper limit on the number of positional
* arguments that can be passed to the function. In this case, this method returns a very large
* number (currently `INT_MAX`, 2147483647, but this may change in the future).
*/
int getMaxPositionalArguments() {
if exists(this.getVararg())
then result = 2147483647 // INT_MAX
else result = count(this.getAnArg())
4 changes: 2 additions & 2 deletions python/ql/lib/semmle/python/objects/ObjectAPI.qll
Original file line number Diff line number Diff line change
@@ -738,9 +738,9 @@ class PythonFunctionValue extends FunctionValue {
else result = "function " + this.getQualifiedName()
}

override int minParameters() { result = this.getScope().getMinArguments() }
override int minParameters() { result = this.getScope().getMinPositionalArguments() }

override int maxParameters() { result = this.getScope().getMaxArguments() }
override int maxParameters() { result = this.getScope().getMaxPositionalArguments() }

/** Gets a control flow node corresponding to a return statement in this function */
ControlFlowNode getAReturnedNode() { result = this.getScope().getAReturnValueFlowNode() }
30 changes: 17 additions & 13 deletions python/ql/src/Functions/SignatureSpecialMethods.ql
Original file line number Diff line number Diff line change
@@ -40,23 +40,25 @@ predicate is_ternary_op(string name) {

predicate is_quad_op(string name) { name = "__setslice__" or name = "__exit__" }

int argument_count(PythonFunctionValue f, string name, ClassValue cls) {
cls.declaredAttribute(name) = f and
(
is_unary_op(name) and result = 1
or
is_binary_op(name) and result = 2
or
is_ternary_op(name) and result = 3
or
is_quad_op(name) and result = 4
)
int argument_count(string name) {
is_unary_op(name) and result = 1
or
is_binary_op(name) and result = 2
or
is_ternary_op(name) and result = 3
or
is_quad_op(name) and result = 4
}

predicate declaredAttributeVar(Class cls, string name, EssaVariable var) {

Check warning

Code scanning / CodeQL

Dead code Warning

This code is never used, and it's not publicly exported.
name = var.getName() and
pragma[only_bind_into](pragma[only_bind_into](var).getAUse()) = cls.getANormalExit()
}

predicate incorrect_special_method_defn(
PythonFunctionValue func, string message, boolean show_counts, string name, ClassValue owner
) {
exists(int required | required = argument_count(func, name, owner) |
exists(int required | required = argument_count(name) and owner.declaredAttribute(name) = func |
/* actual_non_default <= actual */
if required > func.maxParameters()
then message = "Too few parameters" and show_counts = true
@@ -104,7 +106,9 @@ predicate incorrect_get(FunctionValue func, string message, boolean show_counts,
}

string should_have_parameters(PythonFunctionValue f, string name, ClassValue owner) {
exists(int i | i = argument_count(f, name, owner) | result = i.toString())
exists(int i | i = argument_count(name) and owner.declaredAttribute(name) = f |
result = i.toString()
)
or
owner.declaredAttribute(name) = f and
(name = "__get__" or name = "__pow__") and

0 comments on commit 11e6194

Please sign in to comment.