Skip to content

Commit 11e6194

Browse files
committed
Python: Address review comments
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).
1 parent 83cdcdb commit 11e6194

File tree

3 files changed

+28
-18
lines changed

3 files changed

+28
-18
lines changed

python/ql/lib/semmle/python/Function.qll

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,18 @@ class Function extends Function_, Scope, AstNode {
165165
}
166166

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

172-
/** Gets the maximum number of positional arguments that can be correctly passed to this function. */
173-
int getMaxArguments() {
172+
/**
173+
* Gets the maximum number of positional arguments that can be correctly passed to this function.
174+
*
175+
* If the function has a `*vararg` parameter, there is no upper limit on the number of positional
176+
* arguments that can be passed to the function. In this case, this method returns a very large
177+
* number (currently `INT_MAX`, 2147483647, but this may change in the future).
178+
*/
179+
int getMaxPositionalArguments() {
174180
if exists(this.getVararg())
175181
then result = 2147483647 // INT_MAX
176182
else result = count(this.getAnArg())

python/ql/lib/semmle/python/objects/ObjectAPI.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -738,9 +738,9 @@ class PythonFunctionValue extends FunctionValue {
738738
else result = "function " + this.getQualifiedName()
739739
}
740740

741-
override int minParameters() { result = this.getScope().getMinArguments() }
741+
override int minParameters() { result = this.getScope().getMinPositionalArguments() }
742742

743-
override int maxParameters() { result = this.getScope().getMaxArguments() }
743+
override int maxParameters() { result = this.getScope().getMaxPositionalArguments() }
744744

745745
/** Gets a control flow node corresponding to a return statement in this function */
746746
ControlFlowNode getAReturnedNode() { result = this.getScope().getAReturnValueFlowNode() }

python/ql/src/Functions/SignatureSpecialMethods.ql

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,25 @@ predicate is_ternary_op(string name) {
4040

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

43-
int argument_count(PythonFunctionValue f, string name, ClassValue cls) {
44-
cls.declaredAttribute(name) = f and
45-
(
46-
is_unary_op(name) and result = 1
47-
or
48-
is_binary_op(name) and result = 2
49-
or
50-
is_ternary_op(name) and result = 3
51-
or
52-
is_quad_op(name) and result = 4
53-
)
43+
int argument_count(string name) {
44+
is_unary_op(name) and result = 1
45+
or
46+
is_binary_op(name) and result = 2
47+
or
48+
is_ternary_op(name) and result = 3
49+
or
50+
is_quad_op(name) and result = 4
51+
}
52+
53+
predicate declaredAttributeVar(Class cls, string name, EssaVariable var) {
54+
name = var.getName() and
55+
pragma[only_bind_into](pragma[only_bind_into](var).getAUse()) = cls.getANormalExit()
5456
}
5557

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

106108
string should_have_parameters(PythonFunctionValue f, string name, ClassValue owner) {
107-
exists(int i | i = argument_count(f, name, owner) | result = i.toString())
109+
exists(int i | i = argument_count(name) and owner.declaredAttribute(name) = f |
110+
result = i.toString()
111+
)
108112
or
109113
owner.declaredAttribute(name) = f and
110114
(name = "__get__" or name = "__pow__") and

0 commit comments

Comments
 (0)