fix(intents): an ADB-off entry never scans, and a truncated detail is never believed (t21)
The t18 review's three findings, closed with the reviewer's own repro.
F1 (HIGH — the harm was real shells, not a wrong label). `async_scan_intents`
decided between `adb_disabled` and `adb_unavailable` INSIDE `if self._poller is
None:`, so a manager that HELD a poller fell through to the shell loop: with
`adb_enabled: False` and a connected poller the review measured status `fresh`,
one candidate CACHED, and `pm dump com.x …` really sent. The option is a fact
about the ENTRY, so it is now checked once at the top and returns before
anything else — no cache read, no cache write, no shell. The no-poller branch
keeps the OTHER honest answer: with the option ON and nobody to ask, the status
is `adb_unavailable` ("wait or reconnect"), never `adb_disabled` ("go turn the
option on"), because the two have different fixes. Five tests pin it, including
a cache-leak case (a manager with a cached answer whose option is then switched
off answers `adb_disabled`, not the cache) and both statuses with a FORCED scan.
F2 (low, but it fabricated a value that looked real). A capture cut mid-detail
produced `Scheme: "ht` → scheme `"ht` and `Authority: "www.exam` → that
authority, and `_candidate_data` would then prefill the form with a URL no app
can match. Not an injection (everything stays quoted when used), which is
exactly why nothing caught it. `_unquote` now DROPS a value that opens a quote
and never closes it (a lone quote too), so the callers turn it into None: the
candidate survives with its intact action/component and simply carries no
scheme/authority/path — and therefore prefills NO data instead of a broken URL.
A complete quoted value is still read (the anti-overcorrection pin), and the
consequence is pinned at the consumption end too, through the real options-flow
helper.
F3 (low). The floor comment now answers the review in writing, where the next
reader looks: the t18 review's measurement (awaited_calls 6 against a floor of 5,
three other counters within 2) is named, and the verdict is recorded — those ARE
the policy margins (2 for owner-counters because an owner really can be
refactored away, 1 for awaited_calls because six sites cannot carry a percentage
band). The counters were genuinely updated, not dodged: raised to the real sweep
when the code grew (20→24, 70→75, 235→275, 55→63, 1400→1620) and re-derived
twice since (t20 1620→1615, t21 1615→1617 for this unit's blocks).
EVIDENCE THAT THE TESTS PIN THE FIX (not merely pass): the same files were run
against the PRE-fix source (git archive HEAD, a throwaway copy under /tmp) — 9 of
the 11 new tests FAIL there, including the reviewer's repro, which fails with
`assert 'fresh' == 'adb_disabled'`. The two that pass are the deliberate
anti-overcorrection pins: a COMPLETE quoted value is still parsed, and the
no-poller control keeps its own status.
NO REGRESSION: 900 passed / 5 skipped, 901 / 4 with androidtvremote2; the
injection proof, the fixture's candidates with dedup/flagging/order/bound
disclosures, both cache outcomes, the registration round trip through the real
FlowManager, button lifecycle and defaults, the YAML seed rule and §7.1
(supports_response optional, a real return_response call, a no-response call) all
still pass. The strings files are byte-identical (untouched here). Real-HA pattern
collected and RAN 3 files → 74 passed / 0 skipped. Drift exit 0 (1650 blocks).
NOT VERIFIED HERE: the device side remains a scripted double — no real Shield was
asked for its resolver table, so the shell COUNT and the status vocabulary are
what is proven, not real firmware behaviour. No browser either: the form prefill
is asserted on the values the helper returns.
This commit is contained in:
1 parent
6b866019ef
commit
8f064b3247
5 files changed
+264
-16
No files matched your search
@@ -1684,6 +1684,22 @@ class ShieldConnectionManager:
|
||||
# A malformed id never reaches a shell, and never looks like an
|
||||
# answer: the same rule the sweep applies to the rows it keeps.
|
||||
return IntentScanResult(package=name, status=INTENT_SCAN_INVALID_PACKAGE)
|
||||
# t21/F1: THE OPTION IS CHECKED FIRST, ONCE, AND IT RETURNS BEFORE ANYTHING
|
||||
# ELSE — no cache read, no cache write, no shell. This check used to live
|
||||
# INSIDE the no-poller branch below, so an entry that HOLDS a poller while
|
||||
# its own option says ADB is off fell straight through to the dump: the
|
||||
# status was merely mislabelled, but the SHELL WAS REAL, and a scan the
|
||||
# entry was not allowed to run was CACHED as an answer (measured by the t18
|
||||
# review: status `fresh`, one candidate cached, `pm dump com.x …` sent).
|
||||
# "ADB is switched off" is a fact about the ENTRY, so it is decided from the
|
||||
# entry — never inferred from which objects happen to exist.
|
||||
if self._adb_disabled():
|
||||
_LOGGER.debug(
|
||||
"intent scan for %s not attempted (ADB is switched off for this "
|
||||
"entry) — no shell, nothing cached",
|
||||
name,
|
||||
)
|
||||
return IntentScanResult(package=name, status=INTENT_SCAN_ADB_DISABLED)
|
||||
if not force:
|
||||
cached = self._intents.get(name)
|
||||
if cached is not None:
|
||||
@@ -1696,13 +1712,16 @@ class ShieldConnectionManager:
|
||||
truncated=cached.truncated,
|
||||
)
|
||||
if self._poller is None:
|
||||
status = (
|
||||
INTENT_SCAN_ADB_DISABLED
|
||||
if self._adb_disabled()
|
||||
else INTENT_SCAN_ADB_UNAVAILABLE
|
||||
# t21/F1: no poller is NOT the same fact as ADB being switched off. The
|
||||
# option above said ADB is ON, so the honest answer is "the device
|
||||
# cannot be asked right now" (wait, or reconnect), never `adb_disabled`
|
||||
# (go turn the option on) — the two have different fixes.
|
||||
_LOGGER.debug(
|
||||
"intent scan for %s not attempted (ADB is on for this entry but "
|
||||
"there is no poller to ask) — no shell, nothing cached",
|
||||
name,
|
||||
)
|
||||
_LOGGER.debug("intent scan for %s not attempted (%s)", name, status)
|
||||
return IntentScanResult(package=name, status=status)
|
||||
return IntentScanResult(package=name, status=INTENT_SCAN_ADB_UNAVAILABLE)
|
||||
if not self.connected:
|
||||
_LOGGER.debug(
|
||||
"intent scan for %s not attempted (ADB connected: no) — the "
|
||||
|
||||
Reference in new issue
Block a user