Skip to content

fix: address 8 preexisting bugs found during code audit#521

Open
rjullien wants to merge 1 commit into
amosyuen:mainfrom
rjullien:upstream-fix/preexisting-bugs
Open

fix: address 8 preexisting bugs found during code audit#521
rjullien wants to merge 1 commit into
amosyuen:mainfrom
rjullien:upstream-fix/preexisting-bugs

Conversation

@rjullien
Copy link
Copy Markdown

Summary

Code audit found 8 bugs (some multi-entry only, some edge-case crashes). All fixes are minimal and targeted.

Bug Fixes

# File Issue Fix
1 __init__.py Copy-paste: 2nd refresh validates deco instead of clients coordinator clients_coordinator._async_update_data()
2 __init__.py Reboot service: id[0] on None when device has ≠ 1 identifier Generator finds DOMAIN identifier directly
3 __init__.py Service closure captures last-loaded coordinator (multi-entry) Dynamic resolution + duplicate guard
4 __init__.py async_forward_entry_setups via async_create_task (racy) Properly awaited
5 coordinator.py Client coordinator returns None when decos == 0 Returns self.data or {}
6 coordinator.py snake_case_to_title_space(None) when nickname missing Fallback to MAC
7 multiple dict[str:Any] (slice syntax) / cast([str], ...) dict[str, Any], cast(list[str], ...)
8 api.py Cookie regex [a-f0-9]+ too strict for some firmware [a-zA-Z0-9_.-]+

Also

  • manifest.json: key order corrected for hassfest (domain, name, then alphabetical)

Testing

Tested on real TP-Link Deco M4 mesh (4 nodes). No regressions observed.

1. Copy-paste in async_create_and_refresh_coordinators: 2nd block
   refreshed deco_coordinator instead of clients_coordinator during
   config flow validation.

2. async_reboot_deco: id = next(iter(ids)) if len == 1 else None
   then id[0] → TypeError when device has != 1 identifier. Uses
   generator to find the DOMAIN identifier directly.

3. Service closure captures last-loaded coordinator in multi-entry
   setups. Now dynamically resolves coordinator from hass.data by
   matching the device MAC. Guards against duplicate registration.

4. async_forward_entry_setups via async_create_task (racy): now
   properly awaited per HA recommendations.

5. Client coordinator returns None when decos == 0: subsequent access
   to .get() on None would crash. Returns self.data or empty dict.

6. snake_case_to_title_space(None) crash when nickname missing from
   API response: falls back to MAC address.

7. Type annotations: dict[str:Any] (slice syntax) → dict[str, Any],
   cast([str], ...) → cast(list[str], ...).

8. Cookie regex sysauth=[a-f0-9]+ too strict: firmware could return
   uppercase or other chars. Relaxed to [a-zA-Z0-9_.-]+.

Also: manifest key order fixed for hassfest validation.
@rjullien rjullien force-pushed the upstream-fix/preexisting-bugs branch from db8c421 to aa97135 Compare May 29, 2026 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant