quoteCmdArg corrupts arguments containing a literal `"` on cmd surfaces
- Langage dominant
- TypeScript
- Étoiles
- 5
- Forks
- 0
- Merge moyen
- 18 h 32 min
- PR mergées (30 j)
- 216
Description
## `quoteCmdArg` corrupts arguments containing a literal `"` on cmd surfaces
When `dor` forwards a command tail (`dor split -- …`, `dor ensure …`) to a pane whose shell is `cmd.exe`, the host renders the argv with [`quoteCmdArg`](https://github.com/diffplug/dormouse/blob/7f88741dadf837a4711d4c725b6f8a9977c496cc/dor/src/commands/shell-quote.ts#L54-L61). For any argument that contains a double-quote, the output is malformed.
### Trace
```ts
function quoteCmdArg(arg: string): string {
if (arg === '') return '""';
const escaped = arg
.replace(/[%]/g, '%%')
.replace(/([&|<>()^"])/g, '^$1'); // caret-escapes the "
if (WINDOWS_SAFE_ARG.test(arg)) return escaped;
return `"${escaped}"`; // ...then wraps the result in quotes
}
```
For `arg = 'say "hi"'` the function:
1. caret-escapes each `"` → `say ^"hi^"`, then
2. wraps in surrounding quotes → `"say ^"hi^""`.
Inside a cmd double-quoted region, `^` is **not** an escape character — it is literal. So the embedded `^"` does not produce an escaped quote; the first `^"` is read as a literal `^` followed by a quote that **closes** the surrounding quoted region early, and the rest of the argument is re-parsed outside quotes. The argument the launched program receives is not `say "hi"`.
The same belt-and-suspenders pattern (caret-escape *and* wrap in quotes) is what the existing test pins for `a&b` → `"a^&b"` ([cli-output.test.mjs:204-206](https://github.com/diffplug/dormouse/blob/7f88741dadf837a4711d4c725b6f8a9977c496cc/dor/test/cli-output.test.mjs#L204-L206)); for `&`/`(`/`)` the caret inside quotes is merely redundant (those chars are already literal inside quotes), so it's harmless-but-odd. For `"` it is actively wrong, and that case is **untested**.
### Why this needs maintainer input rather than a drive-by fix
Correct cmd-line quoting for a literal `"` depends on how the *receiving* program parses its command line (the msvcrt/`CommandLineToArgvW` convention uses `\"` and `""`; a bare cmd builtin differs). Picking the right escaping is a design decision that should be validated on an actual Windows + cmd.exe host, which this CI environment can't do. Flagging rather than guessing.
### Suggested direction (needs Windows verification)
For the `cmd` kind, escape an embedded `"` by doubling it (`""`) or backslash-escaping (`\"`) *inside* the wrapped form, and don't caret-escape characters that already sit inside the surrounding quotes. Add a `cli-output.test.mjs` case with an embedded `"` to pin whatever behavior is chosen.
_Surfaced by the nightly code-quality survey._
Guide de contribution
Aucun guide de contribution indexé pour ce dépôt
Piste de recherche
Commencez dans dor/src/commands/shell-quote.ts, au niveau de quoteCmdArg, et examinez les attentes existantes dans dor/test/cli-output.test.mjs autour des lignes 204-206. Validez le comportement choisi pour les guillemets littéraux sur un hôte Windows cmd.exe, puis ajoutez un cas de régression avec des guillemets intégrés et confirmez que le programme lancé reçoit l’argument d’origine.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- typescript
- Domaine
- cli
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- Calme
- Clarté
- Plutôt claire
- Accessibilité débutants
- 45/100