Python: Prevent bad join in isinstanceEvaluatesTo

In some cases, we were joining the result of `val.getClass()` against
the first argument of `Types::improperSubclass` before filtering out the
vast majority of tuples by the call to `isinstance_call`.

To fix this, we let `isinstance_call` take care of figuring out the
class of the value being tested. As a bonus, this cleans up the only
other place where `isinstance_call` is used, where we _also_ want to
know the class of the value being tested in the `isinstance` call.
This commit is contained in:
Taus
2021-04-14 16:49:12 +00:00
committed by GitHub
parent a7fcf52267
commit 897d12420b

View File

@@ -1853,8 +1853,10 @@ module Expressions {
private boolean isinstanceEvaluatesTo(
CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val
) {
exists(ObjectInternal cls | isinstance_call(call, use, context, val, cls) |
result = Types::improperSubclass(val.getClass(), cls)
exists(ObjectInternal cls, ObjectInternal val_cls |
isinstance_call(call, use, context, val, val_cls, cls)
|
result = Types::improperSubclass(val_cls, cls)
or
val = ObjectInternal::unknown() and result = maybe()
or
@@ -1866,12 +1868,13 @@ module Expressions {
private predicate isinstance_call(
CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val,
ObjectInternal cls
ObjectInternal val_cls, ObjectInternal cls
) {
exists(ControlFlowNode func, ControlFlowNode arg1 |
call2(call, func, use, arg1) and
points_to_isinstance(func, context) and
PointsToInternal::pointsTo(use, context, val, _) and
val_cls = val.getClass() and
PointsToInternal::pointsTo(arg1, context, cls, _)
)
}
@@ -1993,10 +1996,7 @@ module Expressions {
exists(ObjectInternal sup_or_tuple |
issubclass_call(_, _, _, sub, sup_or_tuple) and sub.isClass() = true
or
exists(ObjectInternal val |
isinstance_call(_, _, _, val, sup_or_tuple) and
sub = val.getClass()
)
exists(ObjectInternal val | isinstance_call(_, _, _, val, sub, sup_or_tuple))
|
sup = sup_or_tuple
or