From 877fc543f290f4d3f8ac697e2295a33a09f02c57 Mon Sep 17 00:00:00 2001 From: Yuichiro Iwata <177282508+y-iwata-bl@users.noreply.github.com> Date: Wed, 6 Nov 2024 18:07:59 +0900 Subject: [PATCH 1/2] Fixed memory leaks related to the cache of securityStateReference. See #93 for details. --- pysnmp/proto/mpmod/rfc3412.py | 6 ++++++ pysnmp/proto/secmod/rfc3414/service.py | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/pysnmp/proto/mpmod/rfc3412.py b/pysnmp/proto/mpmod/rfc3412.py index 11c19606..cf162709 100644 --- a/pysnmp/proto/mpmod/rfc3412.py +++ b/pysnmp/proto/mpmod/rfc3412.py @@ -416,6 +416,9 @@ def prepare_response_message( or pduType is not None and pduType not in rfc3411.CONFIRMED_CLASS_PDUS ): + if securityModel in snmpEngine.security_models: + smHandler = snmpEngine.security_models[securityModel] + smHandler.release_state_information(securityStateReference) raise error.StatusInformation(errorIndication=errind.loopTerminated) # 7.1.3c @@ -523,6 +526,9 @@ def prepare_response_message( elif securityLevel == 3: msgFlags |= 0x03 else: + if securityModel in snmpEngine.security_models: + smHandler = snmpEngine.security_models[securityModel] + smHandler.release_state_information(securityStateReference) raise error.ProtocolError("Unknown securityLevel %s" % securityLevel) if pdu.tagSet in rfc3411.CONFIRMED_CLASS_PDUS: # XXX not needed? diff --git a/pysnmp/proto/secmod/rfc3414/service.py b/pysnmp/proto/secmod/rfc3414/service.py index 31e63c43..5d334c4d 100644 --- a/pysnmp/proto/secmod/rfc3414/service.py +++ b/pysnmp/proto/secmod/rfc3414/service.py @@ -1048,6 +1048,7 @@ def process_incoming_message( "processIncomingMsg: scopedPduData not plaintext %s" % scopedPduData.prettyPrint() ) + self._cache.pop(securityStateReference) raise error.StatusInformation( errorIndication=errind.unknownEngineID ) @@ -1073,6 +1074,7 @@ def process_incoming_message( "processIncomingMsg: will not discover EngineID" ) # free securityStateReference XXX + self._cache.pop(securityStateReference) raise error.StatusInformation( errorIndication=errind.unknownEngineID ) @@ -1154,6 +1156,7 @@ def process_incoming_message( "__SNMPv2-MIB", "snmpInGenErrs" ) snmpInGenErrs.syntax += 1 + self._cache.pop(securityStateReference) raise error.StatusInformation(errorIndication=errind.invalidMsg) else: # empty username used for engineID discovery @@ -1255,6 +1258,7 @@ def process_incoming_message( if usmUserAuthProtocol in self.AUTH_SERVICES: authHandler = self.AUTH_SERVICES[usmUserAuthProtocol] else: + self._cache.pop(securityStateReference) raise error.StatusInformation( errorIndication=errind.authenticationFailure ) @@ -1346,6 +1350,7 @@ def process_incoming_message( ) ) else: + self._cache.pop(securityStateReference) raise error.ProtocolError("Peer SNMP engine info missing") # 3.2.7a @@ -1417,6 +1422,7 @@ def process_incoming_message( ) > 150 ): + self._cache.pop(securityStateReference) raise error.StatusInformation( errorIndication=errind.notInTimeWindow, msgUserName=msgUserName ) @@ -1426,11 +1432,13 @@ def process_incoming_message( if usmUserPrivProtocol in self.PRIV_SERVICES: privHandler = self.PRIV_SERVICES[usmUserPrivProtocol] else: + self._cache.pop(securityStateReference) raise error.StatusInformation( errorIndication=errind.decryptionError, msgUserName=msgUserName ) encryptedPDU = scopedPduData.getComponentByPosition(1) if encryptedPDU is None: # no ciphertext + self._cache.pop(securityStateReference) raise error.StatusInformation( errorIndication=errind.decryptionError, msgUserName=msgUserName ) @@ -1494,6 +1502,7 @@ def process_incoming_message( ) if eoo.endOfOctets.isSameTypeWith(scopedPDU): + self._cache.pop(securityStateReference) raise error.StatusInformation( errorIndication=errind.decryptionError, msgUserName=msgUserName ) @@ -1501,6 +1510,7 @@ def process_incoming_message( # 3.2.8b scopedPDU = scopedPduData.getComponentByPosition(0) if scopedPDU is None: # no plaintext + self._cache.pop(securityStateReference) raise error.StatusInformation( errorIndication=errind.decryptionError, msgUserName=msgUserName ) From b58bc4d09cfc3d416c7630631bd14e52ef9da3e0 Mon Sep 17 00:00:00 2001 From: Lex Li Date: Thu, 7 Nov 2024 02:06:18 -0500 Subject: [PATCH 2/2] Enabled the test case for #93. --- tests/manager_context.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/manager_context.py b/tests/manager_context.py index b925fad6..d86a1c4a 100644 --- a/tests/manager_context.py +++ b/tests/manager_context.py @@ -118,3 +118,4 @@ async def __aexit__(self, exc_type, exc_val, exc_tb): self.manager.transport_dispatcher.job_finished(1) self.manager.close_dispatcher() + self.manager._close()