From 0224bcc77eea8ee6c5b8388e31f7cb9f0054cb68 Mon Sep 17 00:00:00 2001 From: Kurt McKee Date: Mon, 14 Oct 2024 08:05:39 -0500 Subject: [PATCH] Eliminate mutable default parameters from methods Fixed ----- * Eliminate mutable default parameters from methods. Because the parameters are passed to observers, it is possible for an observer to accidentally -- and permanently -- modify a default argument. ```python observers = [lambda x: x.append("bad")] def demo(groups=[]): print(groups) for observer in observers: observer(groups) demo() # [] demo() # ["bad"] demo() # ["bad", "bad"] ``` --- src/smartcard/CardConnection.py | 4 +++- src/smartcard/CardConnectionDecorator.py | 4 +++- src/smartcard/System.py | 4 +++- src/smartcard/pcsc/PCSCCardConnection.py | 4 +++- src/smartcard/pcsc/PCSCReader.py | 11 +++++++---- src/smartcard/reader/ReaderFactory.py | 4 +++- 6 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/smartcard/CardConnection.py b/src/smartcard/CardConnection.py index a29dc2c7..2d58da92 100644 --- a/src/smartcard/CardConnection.py +++ b/src/smartcard/CardConnection.py @@ -187,7 +187,7 @@ def doTransmit(self, command, protocol): transmission.""" return [], 0, 0 - def control(self, controlCode, command=[]): + def control(self, controlCode, command=None): """Send a control command and buffer. Internally calls L{doControl()} class method and notify observers upon command/response events. Subclasses must override the @@ -197,6 +197,8 @@ def control(self, controlCode, command=[]): @param command: list of bytes to transmit """ + if command is None: + command = [] Observable.setChanged(self) Observable.notifyObservers( self, CardConnectionEvent("command", [controlCode, command]) diff --git a/src/smartcard/CardConnectionDecorator.py b/src/smartcard/CardConnectionDecorator.py index 39c253d5..008a866f 100644 --- a/src/smartcard/CardConnectionDecorator.py +++ b/src/smartcard/CardConnectionDecorator.py @@ -85,8 +85,10 @@ def transmit(self, command, protocol=None): """call inner component transmit""" return self.component.transmit(command, protocol) - def control(self, controlCode, command=[]): + def control(self, controlCode, command=None): """call inner component control""" + if command is None: + command = [] return self.component.control(controlCode, command) def getAttrib(self, attribId): diff --git a/src/smartcard/System.py b/src/smartcard/System.py index 257459b2..58fa9f2b 100644 --- a/src/smartcard/System.py +++ b/src/smartcard/System.py @@ -28,7 +28,7 @@ import smartcard.reader.ReaderFactory -def readers(groups=[]): +def readers(groups=None): """Returns the list of smartcard readers in groups as L{smartcard.reader.Reader}. @@ -39,6 +39,8 @@ def readers(groups=[]): >>> r=smartcard.readers(['SCard$DefaultReaders', 'MyReaderGroup']) """ + if groups is None: + groups = [] return smartcard.reader.ReaderFactory.ReaderFactory.readers(groups) diff --git a/src/smartcard/pcsc/PCSCCardConnection.py b/src/smartcard/pcsc/PCSCCardConnection.py index c49dce4e..240a802c 100644 --- a/src/smartcard/pcsc/PCSCCardConnection.py +++ b/src/smartcard/pcsc/PCSCCardConnection.py @@ -285,7 +285,7 @@ def doTransmit(self, command, protocol=None): data = [(x + 256) % 256 for x in response[:-2]] return list(data), sw1, sw2 - def doControl(self, controlCode, command=[]): + def doControl(self, controlCode, command=None): """Transmit a control command to the reader and return response. @param controlCode: control command @@ -294,6 +294,8 @@ def doControl(self, controlCode, command=[]): @return: response are the response bytes (if any) """ + if command is None: + command = [] CardConnection.doControl(self, controlCode, command) hresult, response = SCardControl(self.hcard, controlCode, command) if hresult != SCARD_S_SUCCESS: diff --git a/src/smartcard/pcsc/PCSCReader.py b/src/smartcard/pcsc/PCSCReader.py index 9ee090aa..470f49f4 100644 --- a/src/smartcard/pcsc/PCSCReader.py +++ b/src/smartcard/pcsc/PCSCReader.py @@ -31,14 +31,15 @@ from smartcard.scard import * -def __PCSCreaders__(hcontext, groups=[]): +def __PCSCreaders__(hcontext, groups=None): """Returns the list of PCSC smartcard readers in PCSC group. If group is not specified, returns the list of all PCSC smartcard readers. """ - # in case we have a string instead of a list - if isinstance(groups, str): + if groups is None: + groups = [] + elif isinstance(groups, str): groups = [groups] hresult, readers = SCardListReaders(hcontext, groups) if hresult != SCARD_S_SUCCESS: @@ -104,7 +105,9 @@ def create(readername): return PCSCReader(readername) @staticmethod - def readers(groups=[]): + def readers(groups=None): + if groups is None: + groups = [] creaders = [] hcontext = PCSCContext().getContext() diff --git a/src/smartcard/reader/ReaderFactory.py b/src/smartcard/reader/ReaderFactory.py index e11ecbd9..d58df774 100644 --- a/src/smartcard/reader/ReaderFactory.py +++ b/src/smartcard/reader/ReaderFactory.py @@ -53,7 +53,9 @@ def createReader(clazz, readername): return ReaderFactory.factories[clazz].create(readername) @staticmethod - def readers(groups=[]): + def readers(groups=None): + if groups is None: + groups = [] zreaders = [] for fm in ReaderFactory.factorymethods: zreaders += fm(groups)