Fix crashes on invalid UTF-8 in device name fields
A device name is display-only, but three code paths decode it strictly and raise UnicodeDecodeError, aborting the whole operation: - handle_device_discovery: crashes 'solaar pair' during Bolt discovery - BoltReceiver.device_codename: crashes 'solaar show' and 'solaar unpair' - get_friendly_name: crashes 'solaar show' after device enumeration Observed in the wild with an MX Master 3S whose user-writable friendly name field contained 0xc3 0x23 (invalid UTF-8). The Bolt receiver copies this name at pairing time, so the bad bytes surface from both the receiver registers and the live HID++ 2.0 feature, making the device impossible to pair, list, or unpair with Solaar. Decode with errors='replace' so a garbage name renders as replacement characters instead of making the device unusable.
This commit is contained in:
parent
8a941c5553
commit
822b762b3c
|
|
@ -1891,7 +1891,7 @@ class Hidpp20:
|
|||
logger.error("failed to read whole name of %s (expected %d chars)", device, name_length)
|
||||
return None
|
||||
|
||||
return name.decode("utf-8")
|
||||
return name.decode("utf-8", errors="replace")
|
||||
|
||||
def get_battery_status(self, device: Device):
|
||||
report = device.feature_request(SupportedFeature.BATTERY_STATUS)
|
||||
|
|
|
|||
|
|
@ -531,7 +531,7 @@ def handle_device_discovery(receiver: Receiver, notification: HIDPPNotification)
|
|||
receiver.pairing.device_address = notification.data[6:12]
|
||||
receiver.pairing.device_authentication = notification.data[14]
|
||||
elif notification.data[1] == 1:
|
||||
receiver.pairing.device_name = notification.data[3 : 3 + notification.data[2]].decode("utf-8")
|
||||
receiver.pairing.device_name = notification.data[3 : 3 + notification.data[2]].decode("utf-8", errors="replace")
|
||||
return True
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -497,7 +497,7 @@ class BoltReceiver(Receiver):
|
|||
codename = self.read_register(Registers.RECEIVER_INFO, InfoSubRegisters.BOLT_DEVICE_NAME + n, 0x01)
|
||||
if codename:
|
||||
codename = codename[3 : 3 + min(14, ord(codename[2:3]))]
|
||||
return codename.decode("ascii")
|
||||
return codename.decode("ascii", errors="replace")
|
||||
|
||||
def device_pairing_information(self, n: int) -> dict:
|
||||
pair_info = self.read_register(Registers.RECEIVER_INFO, InfoSubRegisters.BOLT_PAIRING_INFORMATION + n)
|
||||
|
|
|
|||
Loading…
Reference in New Issue