Update test outputs + fix semantics

This commit is contained in:
Joe Farebrother
2025-07-02 10:53:28 +01:00
parent 732c818916
commit 99a05ed5a4
5 changed files with 40 additions and 36 deletions

View File

@@ -19,17 +19,16 @@ Function getASuperCallTarget(Class mroBase, Function meth, DataFlow::MethodCallN
meth = call.getScope() and
getADirectSuperclass*(mroBase) = meth.getScope() and
call.calls(_, meth.getName()) and
exists(Function target, Class nextMroBase |
(result = target or result = getASuperCallTarget(nextMroBase, target, _))
|
exists(Function target | (result = target or result = getASuperCallTarget(mroBase, target, _)) |
superCall(call, _) and
nextMroBase = mroBase and
target =
findFunctionAccordingToMroKnownStartingClass(getNextClassInMroKnownStartingClass(meth.getScope(),
mroBase), mroBase, meth.getName())
or
callsMethodOnClassWithSelf(meth, call, nextMroBase, _) and
target = findFunctionAccordingToMro(nextMroBase, meth.getName())
exists(Class called |
callsMethodOnClassWithSelf(meth, call, called, _) and
target = findFunctionAccordingToMroKnownStartingClass(called, mroBase, meth.getName())
)
)
}

View File

@@ -1,2 +1,2 @@
| multiple_del.py:17:1:17:17 | class Y3 | Class Y3 may not be cleaned up properly as $@ may be called multiple times during destruction. | multiple_del.py:9:5:9:22 | Function __del__ | method Y1.__del__ |
| multiple_del.py:34:1:34:17 | class Z3 | Class Z3 may not be cleaned up properly as $@ may be called multiple times during destruction. | multiple_del.py:26:5:26:22 | Function __del__ | method Z1.__del__ |
| multiple_del.py:21:5:21:22 | Function __del__ | This delete method calls $@ multiple times. | multiple_del.py:9:5:9:22 | Function __del__ | Y1.__del__ |
| multiple_del.py:43:5:43:22 | Function __del__ | This delete method calls $@ multiple times. | multiple_del.py:32:5:32:22 | Function __del__ | Z1.__del__ |

View File

@@ -2,37 +2,48 @@
class Base(object):
def __del__(self):
pass
print("Base del")
class Y1(Base):
def __del__(self):
print("Y1 del")
super(Y1, self).__del__()
class Y2(Base):
def __del__(self):
print("Y2 del")
super(Y2, self).__del__() #When `type(self) == Y3` this calls `Y1.__del__`
class Y3(Y2, Y1):
def __del__(self):
def __del__(self): # $ Alert
print("Y3 del")
Y1.__del__(self)
Y2.__del__(self)
a = Y3()
del a
#Calling a method multiple times by using explicit calls when a base inherits from other base
class Z1(object):
def __del__(self):
pass
print("Z1 del")
class Z2(Z1):
def __del__(self):
print("Z2 del")
Z1.__del__(self)
class Z3(Z2, Z1):
def __del__(self):
def __del__(self): # $ Alert
print("Z3 del")
Z1.__del__(self)
Z2.__del__(self)
b = Z3()
del b

View File

@@ -1,2 +1,2 @@
| multiple_init.py:17:1:17:17 | class C3 | Class C3 may not be initialized properly as $@ may be called multiple times during initialization. | multiple_init.py:9:5:9:23 | Function __init__ | method C1.__init__ |
| multiple_init.py:34:1:34:17 | class D3 | Class D3 may not be initialized properly as $@ may be called multiple times during initialization. | multiple_init.py:26:5:26:23 | Function __init__ | method D1.__init__ |
| multiple_init.py:21:5:21:23 | Function __init__ | This initialization method calls $@ multiple times. | multiple_init.py:9:5:9:23 | Function __init__ | C1.__init__ |
| multiple_init.py:42:5:42:23 | Function __init__ | This initialization method calls $@ multiple times. | multiple_init.py:31:5:31:23 | Function __init__ | D1.__init__ |

View File

@@ -7,70 +7,64 @@ class Base(object):
class C1(Base):
def __init__(self):
print("C1 init")
super(C1, self).__init__()
class C2(Base):
def __init__(self):
print("C2 init")
super(C2, self).__init__() #When `type(self) == C3` this calls `C1.__init__`
class C3(C2, C1):
def __init__(self):
def __init__(self): # $ Alert
print("C3 init")
C1.__init__(self)
C2.__init__(self)
C3()
#Calling a method multiple times by using explicit calls when a base inherits from other base
class D1(object):
def __init__(self):
pass
print("D1 init")
class D2(D1):
def __init__(self):
print("D2 init")
D1.__init__(self)
class D3(D2, D1):
def __init__(self):
def __init__(self): # $ Alert
print("D3 init")
D1.__init__(self)
D2.__init__(self)
D3()
#OK to call object.__init__ multiple times
class E1(object):
def __init__(self):
print("E1 init")
super(E1, self).__init__()
class E2(object):
def __init__(self):
print("E2 init")
object.__init__(self)
class E3(E2, E1):
def __init__(self):
def __init__(self): # OK: builtin init methods are fine.
E1.__init__(self)
E2.__init__(self)
#Two invocations, but can only be called once
class F1(Base):
def __init__(self, cond):
if cond:
Base.__init__(self)
else:
Base.__init__(self)
#Single call, splitting causes what seems to be multiple invocations.
class F2(Base):
def __init__(self, cond):
if cond:
pass
if cond:
pass
Base.__init__(self)
E3()