Skip to content

Windows: rdc capture mangles child app args via POSIX shlex.quote (backslash paths get literally single-quoted) #257

Description

@borisbat

What happened?

On Windows, rdc capture -- <exe> <args> passes arguments to the launched app wrapped in literal single quotes whenever an argument contains a backslash. The app then receives e.g. 'C:\path\file' — with the quotes as part of the string — and can't find the file.

Steps to reproduce

  1. rdc capture -o out.rdc -- C:\tools\app.exe C:\data\input.txt
  2. The launched app sees its argument as 'C:\data\input.txt' (literal single-quotes included).

Concrete example (launching the daslang interpreter):

rdc capture -o out.rdc -- D:\bin\daslang.exe -load_module D:\mod D:\path\script.das
→ error[20605]: missing prerequisite ''D:\path\script.das''; file not found

(Note the doubled quotes in the diagnostic — daslang prints the bad filename in single-quotes, and the filename it received already had single-quotes.)

Expected: arguments passed through unmodified.
Actual: any backslash-containing arg is wrapped in '...'.

Root cause

The child command line handed to renderdoc.ExecuteAndInject(...) is built with POSIX shlex.quote. shlex.quote single-quotes any string containing a character outside its safe set [A-Za-z0-9_@%+=:,./-] — and the Windows path separator \ is not in that set. On Windows, single quotes are not shell quoting; they become literal characters in the argument string.

Recommended fix

Build the child command line with platform-appropriate quoting:

  • Windows: subprocess.list2cmdline(args) (MSVCRT rules — only wraps args with spaces/tabs/" in double quotes), not shlex.quote.
  • POSIX: keep shlex.join / shlex.quote.

Since ExecuteAndInject takes a single cmdline string, the safest is to branch on os.name/sys.platform when joining [app] + app_args.

Workaround: pass forward-slash paths (/ is in shlex's safe set, so it isn't quoted) — incidental, not a real fix.

OS / Platform

Windows 11

Python version

3.12.13

rdc-cli version

0.5.6

Capture file

N/A — fails before any capture is produced.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions