diff --git a/python/ql/lib/change-notes/2025-02-26-add-get-min-max-parameters-to-function-class.md b/python/ql/lib/change-notes/2025-02-26-add-get-min-max-parameters-to-function-class.md new file mode 100644 index 000000000000..f35b0981bafc --- /dev/null +++ b/python/ql/lib/change-notes/2025-02-26-add-get-min-max-parameters-to-function-class.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- + +- Added the methods `getMinArguments` and `getMaxArguments` to the `Function` class. These return the minimum and maximum positional arguments that the given function accepts. diff --git a/python/ql/lib/semmle/python/Function.qll b/python/ql/lib/semmle/python/Function.qll index c3d5f7c801ea..589d7f471611 100644 --- a/python/ql/lib/semmle/python/Function.qll +++ b/python/ql/lib/semmle/python/Function.qll @@ -163,6 +163,24 @@ class Function extends Function_, Scope, AstNode { ret.getValue() = result.getNode() ) } + + /** Gets the minimum number of positional arguments that can be correctly passed to this function. */ + 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. + * + * 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()) + } } /** A def statement. Note that FunctionDef extends Assign as a function definition binds the newly created function */ diff --git a/python/ql/lib/semmle/python/objects/ObjectAPI.qll b/python/ql/lib/semmle/python/objects/ObjectAPI.qll index dc1363b2ebe2..4a36ec6d847f 100644 --- a/python/ql/lib/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/lib/semmle/python/objects/ObjectAPI.qll @@ -738,21 +738,9 @@ class PythonFunctionValue extends FunctionValue { else result = "function " + this.getQualifiedName() } - override int minParameters() { - exists(Function f | - f = this.getScope() and - result = count(f.getAnArg()) - count(f.getDefinition().getArgs().getADefault()) - ) - } + override int minParameters() { result = this.getScope().getMinPositionalArguments() } - override int maxParameters() { - exists(Function f | - f = this.getScope() and - if exists(f.getVararg()) - then result = 2147483647 // INT_MAX - else result = count(f.getAnArg()) - ) - } + 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() }