Skip to content

Commit d540bf6

Browse files
authored
Merge pull request github#3039 from BekaValentine/python-objectapi-to-valueapi-returnvalueignored
Python: ObjectAPI to ValueAPI: ReturnValueIgnored
2 parents 32cf0f1 + cc53b15 commit d540bf6

File tree

3 files changed

+18
-8
lines changed

3 files changed

+18
-8
lines changed

python/ql/src/Functions/ReturnValueIgnored.ql

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@
1515
*/
1616

1717
import python
18+
import semmle.python.objects.Callables
1819

1920
predicate meaningful_return_value(Expr val) {
2021
val instanceof Name
2122
or
2223
val instanceof BooleanLiteral
2324
or
24-
exists(FunctionObject callee |
25+
exists(FunctionValue callee |
2526
val = callee.getACall().getNode() and returns_meaningful_value(callee)
2627
)
2728
or
28-
not exists(FunctionObject callee | val = callee.getACall().getNode()) and not val instanceof Name
29+
not exists(FunctionValue callee | val = callee.getACall().getNode()) and not val instanceof Name
2930
}
3031

3132
/* Value is used before returning, and thus its value is not lost if ignored */
@@ -35,10 +36,10 @@ predicate used_value(Expr val) {
3536
)
3637
}
3738

38-
predicate returns_meaningful_value(FunctionObject f) {
39-
not exists(f.getFunction().getFallthroughNode()) and
39+
predicate returns_meaningful_value(FunctionValue f) {
40+
not exists(f.getScope().getFallthroughNode()) and
4041
(
41-
exists(Return ret, Expr val | ret.getScope() = f.getFunction() and val = ret.getValue() |
42+
exists(Return ret, Expr val | ret.getScope() = f.getScope() and val = ret.getValue() |
4243
meaningful_return_value(val) and
4344
not used_value(val)
4445
)
@@ -48,7 +49,9 @@ predicate returns_meaningful_value(FunctionObject f) {
4849
* Ignore __import__ as it is often called purely for side effects
4950
*/
5051

51-
f.isC() and f.getAnInferredReturnType() != theNoneType() and not f.getName() = "__import__"
52+
f.isBuiltin() and
53+
f.getAnInferredReturnType() != ClassValue::nonetype() and
54+
not f.getName() = "__import__"
5255
)
5356
}
5457

@@ -61,7 +64,7 @@ predicate wrapped_in_try_except(ExprStmt call) {
6164
)
6265
}
6366

64-
from ExprStmt call, FunctionObject callee, float percentage_used, int total
67+
from ExprStmt call, FunctionValue callee, float percentage_used, int total
6568
where
6669
call.getValue() = callee.getACall().getNode() and
6770
returns_meaningful_value(callee) and

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,13 @@ abstract class FunctionValue extends CallableValue {
581581
exists(Expr expr, AstNode origin | expr.pointsTo(this, origin) | not origin instanceof Lambda)
582582
)
583583
}
584+
585+
/** Gets a class that this function may return */
586+
ClassValue getAnInferredReturnType() {
587+
result = TBuiltinClassObject(this.(BuiltinFunctionObjectInternal).getReturnType())
588+
or
589+
result = TBuiltinClassObject(this.(BuiltinMethodObjectInternal).getReturnType())
590+
}
584591
}
585592

586593
/** Class representing Python functions */
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
| functions_test.py:159:5:159:9 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | functions_test.py:12:1:12:11 | Function ok2 | ok2 |
22
| functions_test.py:160:5:160:9 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | functions_test.py:36:1:36:11 | Function ok4 | ok4 |
3-
| functions_test.py:161:5:161:17 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | file://:Compiled Code:0:0:0:0 | Builtin-function sorted | sorted |
3+
| functions_test.py:161:5:161:17 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | file://:0:0:0:0 | Builtin-function sorted | sorted |

0 commit comments

Comments
 (0)