Merge pull request #11029 from devdavidejesus/fix-8302-feeslider-wallet-none
What changed, and why it matters
This is a small bug-fix patch for Electrum's QML (mobile-style) user interface. It prevents the app from crashing when a wallet is closed while a fee-slider screen is still active. The code now checks whether a wallet still exists before trying to read its settings or compare transactions. There is no indication this can be used to steal funds or attack users remotely.
Treat as a routine stability fix. No urgent security action is required. Users of the QML build may benefit from updating to avoid a UI crash when closing a wallet during fee-slider use.
Security signals we found
Null-pointer / NoneType dereference fix in UI code
Defensive guard added around wallet lifecycle edge case
No cryptographic, network, or privilege changes present
Evidence from the diff
The commit guards three code paths in electrum/gui/qml/qetxfinalizer.py against self._wallet being None. The wallet setter now only copies config and calls read_config() when the new wallet is non-None. Two event handlers (on_event_verified and on_event_removed_transaction) now short-circuit if self._wallet is None before dereferencing self._wallet.wallet. This fixes a NoneType AttributeError/crash when the current wallet is closed while the fee-slider/transaction-finalizer object is still alive.
Changed components
electrum/gui/qml/qetxfinalizer.pyQML fee slider / transaction finalizer UIInspect captured patch +5 / −4
### electrum/gui/qml/qetxfinalizer.py
@@ -77,8 +77,9 @@ def wallet(self, wallet: QEWallet):
assert wallet is None or isinstance(wallet, QEWallet)
if self._wallet != wallet:
self._wallet = wallet
- self._config = self._wallet.wallet.config
- self.read_config()
+ if wallet is not None: # None e.g. when the current wallet is closed
+ self._config = wallet.wallet.config
+ self.read_config()
self.walletChanged.emit()
sliderStepsChanged = pyqtSignal()
@@ -622,14 +623,14 @@ def on_destroy(self):
@event_listener
def on_event_verified(self, wallet, txid, info):
- if wallet == self._wallet.wallet and txid == self._txid:
+ if self._wallet and wallet == self._wallet.wallet and txid == self._txid:
self._logger.debug('verified event for our txid %s' % txid)
self.tx_verified()
self.txMined.emit()
@event_listener
def on_event_removed_transaction(self, wallet, tx):
- if wallet == self._wallet.wallet and tx.txid() == self._txid:
+ if self._wallet and wallet == self._wallet.wallet and tx.txid() == self._txid:
self._logger.debug('remove tx for our txid %s' % self._txid)
self.tx_removed()
self.txRemoved.emit()Why this scored 17/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.