fix(android): shell-quote free-text arguments reaching the device shell - #1645
fix(android): shell-quote free-text arguments reaching the device shell#1645thymikee wants to merge 1 commit into
Conversation
Text entry (input text) and clipboard write (cmd clipboard set text) now quote their free-form text argument with the same shellQuoteIfNeeded helper app-lifecycle.ts already uses for deep-link URLs and launch arguments, and app-lifecycle.ts's local duplicate of that helper is retired in favor of the shared one. Multi-word clipboard writes also now arrive at the device as a single argument instead of being re-tokenized into separate ones. Updates the provider-scenario test harness's scripted clipboard-state simulator to unwrap shell quoting the same way a device shell does, so it keeps modelling what the device actually receives.
8d1440f to
b6ab288
Compare
Size Report
Startup median (7 runs, lower is better):
Top changed chunks:
|
|
Reviewed exact head Not ready yet: required live Android evidence is absent. Rebuild the Android artifacts, run without the test IME/provider-native injector, and attach literal UI read-back for shell-metacharacter |
|
Coverage is red here, and it is not attributable to this change. Evidence, since "unrelated flake" deserves proof rather than assertion:
Root cause: the test asserts absolute indices into a timing-dependent event array. const firstStep = hookValue(hooks, 3, 'onTestStep');
expect(hookValue(hooks, 5, 'onTestStep')).toMatchObject({ attempt: 2, … });CI observed 6 hooks where 8 were expected ( This is a latent defect on main. What this branch does is change which Android provider-scenario files run concurrently in the same shard, shifting the scheduling enough to expose it — deterministically for this file set, which is why a rerun reproduced it exactly. Note it is outside Not fixing it in this PR — that would bundle an unrelated main-branch test defect into an Android platform change, which is exactly the mixing the split was meant to undo. Happy to send it as its own PR. This PR stays a draft regardless, pending live emulator evidence with the test IME off. |
Live Android evidence — exact head
|
|
Evidence re-review at unchanged head Readiness is still blocked by two concrete residuals:
No |
Summary
adb shell <argv>joins its arguments and the device's shell re-tokenizes the result.app-lifecycle.tsalready accounts for that and quotes deep-link URLs and launch arguments; the two paths carrying genuinely free-form text did not.type/fill(input text) andclipboard write(cmd clipboard set text) now quote their text argument with the sharedshellQuoteIfNeededhelper — the same oneapp-lifecycle.tsuses. Its byte-identical local copy,quoteAndroidShellArg, is retired in favour of the shared one.The ASCII gate on the text path (
assertAndroidShellTextSupported) is not a substitute: it only rejects characters outside0x20–0x7e, and every shell-significant character sits inside that range.User-visible behaviour change: multi-word
clipboard writenow reaches the device as a single argument instead of being re-tokenized into several.Validation
pnpm test:integration:providergreen (42/42 files, 149/149 tests). Four new unit tests; the two that pin quoting were proven to fail without the change — reverted, run,2 failed | 26 passed, restored:One harness change deserves a look:
provider-scenarios/android-world.tssimulated the device clipboard by exact-matching the joined argv, so quoting stopped the match firing and an unrelated assertion failed first. That harness was modelling the unquoted argv as correct — encoding the pre-fix behaviour — so it now matches the command prefix and shell-unquotes the value, mirroring what a real device shell does beforecmdsees it. Matching the new quoted literal instead would have re-frozen the same mistake one step over.Residual risk — draft until live evidence
No emulator run yet, so this stays a draft per the repo's device-readiness rule. The run must execute with the test IME off (
open --test-imenot set, no provider-native injector), or theadb shellfallback being fixed never executes and a green result proves nothing.Scope
7 files. Split out of #1639 per review; found by a read-only codebase audit. Local gates are currently unreliable on this machine due to a competing test run — pushed on GitHub CI's authority with maintainer agreement.