mirror of
https://github.com/github/codeql.git
synced 2026-05-03 12:45:27 +02:00
add return-or-yield-outside-of-function Python query
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# invalid class with return outside of a function
|
||||
class InvalidClass1(object):
|
||||
if [1, 2, 3]:
|
||||
return "Exists"
|
||||
|
||||
# invalid statement with yield outside of a function
|
||||
for i in [1, 2, 3]:
|
||||
yield i
|
||||
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>In Python, <code>return</code> and <code>yield</code> statements as well as <code>yield from</code>
|
||||
expression can only be used within a function. Having them placed outside of a function or a class
|
||||
method will raise a <code>SyntaxError</code> at runtime.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>The presence of <code>return</code> and <code>yield</code> statements or <code>yield from</code>
|
||||
expression outside of a function or a class method suggests a logical error, so it is not possible
|
||||
to suggest a general fix.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In this example, a <code>return</code> statement is used outside of a class method in a class and
|
||||
a <code>yield</code> statement is used outside of a function in a scope of a module.</p>
|
||||
<sample src="ReturnOrYieldOutsideOfFunction.py" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Python reference: <a href="https://docs.python.org/3.7/reference/simple_stmts.html#the-return-statement">
|
||||
The return statement</a>.</li>
|
||||
<li>Python reference: <a href="https://docs.python.org/3.7/reference/simple_stmts.html#yield">
|
||||
The yield statement</a>.</li>
|
||||
<li>Python PEP-380: <a href="https://docs.python.org/3/whatsnew/3.3.html#pep-380">
|
||||
The yield from expression</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
25
python/ql/src/Statements/ReturnOrYieldOutsideOfFunction.ql
Normal file
25
python/ql/src/Statements/ReturnOrYieldOutsideOfFunction.ql
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @name return or yield are used outside of a function
|
||||
* @description return and yield statements should be used only within a function.
|
||||
* @kind problem
|
||||
* @tags reliability
|
||||
* correctness
|
||||
* @problem.severity error
|
||||
* @sub-severity low
|
||||
* @precision very-high
|
||||
* @id py/return-or-yield-outside-of-function
|
||||
*/
|
||||
|
||||
import python
|
||||
|
||||
from AstNode node, string kind
|
||||
where
|
||||
not node.getScope() instanceof Function and
|
||||
(
|
||||
node instanceof Return and kind = "return"
|
||||
or
|
||||
node instanceof Yield and kind = "yield"
|
||||
or
|
||||
node instanceof YieldFrom and kind = "yield from"
|
||||
)
|
||||
select node, "'" + kind + "' is used outside of a function."
|
||||
@@ -0,0 +1,9 @@
|
||||
| ReturnOrYieldOutsideOfFunction_test.py:31:9:31:23 | Return | 'return' is used outside of a function. |
|
||||
| ReturnOrYieldOutsideOfFunction_test.py:36:9:36:15 | Yield | 'yield' is used outside of a function. |
|
||||
| ReturnOrYieldOutsideOfFunction_test.py:41:9:41:25 | YieldFrom | 'yield from' is used outside of a function. |
|
||||
| ReturnOrYieldOutsideOfFunction_test.py:45:5:45:12 | Return | 'return' is used outside of a function. |
|
||||
| ReturnOrYieldOutsideOfFunction_test.py:49:5:49:11 | Yield | 'yield' is used outside of a function. |
|
||||
| ReturnOrYieldOutsideOfFunction_test.py:53:5:53:16 | YieldFrom | 'yield from' is used outside of a function. |
|
||||
| ReturnOrYieldOutsideOfFunction_test.py:57:1:57:14 | YieldFrom | 'yield from' is used outside of a function. |
|
||||
| ReturnOrYieldOutsideOfFunction_test.py:60:1:60:12 | Return | 'return' is used outside of a function. |
|
||||
| ReturnOrYieldOutsideOfFunction_test.py:63:1:63:11 | Yield | 'yield' is used outside of a function. |
|
||||
@@ -0,0 +1 @@
|
||||
Statements/ReturnOrYieldOutsideOfFunction.ql
|
||||
@@ -0,0 +1,63 @@
|
||||
# valid class with return inside a function
|
||||
class ValidClass1(object):
|
||||
def class_method(self):
|
||||
return False
|
||||
|
||||
# valid class with yield inside a function
|
||||
class ValidClass2(object):
|
||||
def class_method(self):
|
||||
yield 1
|
||||
|
||||
# valid class with yield from inside a function
|
||||
class ValidClass3(object):
|
||||
def class_method(self):
|
||||
yield from [1, 2]
|
||||
|
||||
# valid function with the return statement
|
||||
def valid_func1():
|
||||
return True
|
||||
|
||||
# valid function with the yield statement
|
||||
def valid_func2():
|
||||
yield 1
|
||||
|
||||
# valid function with the yield from statement
|
||||
def valid_func3():
|
||||
yield from [1, 2]
|
||||
|
||||
# invalid class with return outside of a function
|
||||
class InvalidClass1(object):
|
||||
if [1, 2, 3]:
|
||||
return "Exists"
|
||||
|
||||
# invalid class with yield outside of a function
|
||||
class InvalidClass2(object):
|
||||
while True:
|
||||
yield 1
|
||||
|
||||
# invalid class with yield from outside of a function
|
||||
class InvalidClass2(object):
|
||||
while True:
|
||||
yield from [1, 2]
|
||||
|
||||
# invalid statement with return outside of a function
|
||||
for i in [1, 2, 3]:
|
||||
return i
|
||||
|
||||
# invalid statement with yield outside of a function
|
||||
for i in [1, 2, 3]:
|
||||
yield i
|
||||
|
||||
# invalid statement with yield from outside of a function
|
||||
for i in [1, 2, 3]:
|
||||
yield from i
|
||||
|
||||
# invalid statement with yield from outside of a function
|
||||
var = [1,2,3]
|
||||
yield from var
|
||||
|
||||
# invalid statement with return outside of a function
|
||||
return False
|
||||
|
||||
# invalid statement with yield outside of a function
|
||||
yield False
|
||||
Reference in New Issue
Block a user