Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vscode adding escapes to args supplied via launch.json configuration. python sys.argv sees VS code's arguments not those specified in launch.json. #149391

Closed
AshleyT3 opened this issue May 12, 2022 · 5 comments
Assignees

Comments

@AshleyT3
Copy link

Does this issue occur when all extensions are disabled?: Yes

Steps to Reproduce:

  1. Prepare VSCode for minimal Python development, meaning activate the Python extension.
  2. Start VSCode, create a directory with a VSCode workspace.
  3. Create a new Python script display_argv.py with the source code shown below.
  4. Choose Run/Add Configuration or start debugging display_argv.py to kick off a prompt that ultimately causes a default launch.json to be created.
  5. In the launch.json, add an "args" field with an array containing a single arg element of "C:\". Note, in the example launch.json shown below, there are two slashes which are required by VSCode to satisfy its syntax checker since json requires escaping slash (and fwiw, VSCode fails to launch the script without escaping the slash).
  6. Run or debug display_argv.py using the new launch.json configuration with the one argument. Notice that the C:\ argument is received by Python as C:\\ (4 characters). Effectively, VSCode is adding a character to the specified argument.

launch.json with C:\ argument:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "justMyCode": true,
            "args": [
                "C:\\"
            ]
        }
    ]
}

display_argv.py:

import sys
print(sys.argv)
print(f"sys.argv[1]={sys.argv[1]} len={len(sys.argv[1])} sys.argv[1][-2]={sys.argv[1][-2]} sys.argv[1][-1]={sys.argv[1][-1]}")

The display_argv.py output observed upon repro:

['c:\\test\\display_argv.py', 'C:\\\\']
sys.argv[1]=C:\\ and is len=4 sys.argv[1][-2]=\ sys.argv[1][-1]=\
@nlarusstone
Copy link

I'm also encountering this and it seems to be due to the most recent update:

Version: 1.67.1
Commit: da15b6fd3ef856477bf6f4fb29ba1b7af717770d
Date: 2022-05-06T12:37:16.526Z (1 wk ago)
Electron: 17.4.1
Chromium: 98.0.4758.141
Node.js: 16.13.0
V8: 9.8.177.13-electron.0
OS: Darwin x64 20.6.0

My configuration contains a < sign and it's getting escaped:

        {
            "name": "Cluster",
            "type": "python",
            "justMyCode": false,
            "request": "launch",
            "program": "${workspaceFolder}/manage.py",
            "args": [
                "shell",
                "<",
                "${workspaceFolder}/launch_cluster.py"
            ],
            "preLaunchTask": "checkServer",
            "django": true
        },

Produces an error because the generated command is: manage.py shell \< launch_cluster.py

@roblourens
Copy link
Member

This will be fixed in 1.67.2 (releasing in a couple hours) #148887

@jcollinsZF
Copy link

I don't think this issue was fully fixed. I still see spaces being escaped. Here is a minimal reproducible example.

{
  "name": "Example escaped launch.json config",
  "type": "python",
  "request": "launch",
  "program": "example.py",
  "args": [
    "foo bar"
  ]
},

I get the output:

/usr/bin/env /srv/venv/bin/python /root/.vscode-server/extensions/ms-python.python-2022.6.2/pythonFiles/lib/python/debugpy/launcher 44853 -- example.py foo\ bar

Notice how a slash was added between "foo" and "bar" example.py foo\ bar

In this contrived example I understand that I could fix this by using

  "args": [
    "foo",
    "bar"
  ]

But I cannot do that with how I actually want to use launch.json

My real world example is this:

{
    "name": "Python: Django Debug Single Test",
    "type": "python",
    "request": "launch",
    "program": "${workspaceFolder}/manage.py",
    "args": [
        "test",
        "`echo -n ${relativeFileDirname} | tr \/ .`.${fileBasenameNoExtension}"
    ],
    "django": true
}

but every space in that second argument gets escaped and it breaks the command :(

@roblourens
Copy link
Member

The history is this - we were not fully escaping arguments, making it impossible to pass some special characters to a program as args. #145265. I think we never intended to enable arbitrary shell scripts in launch.json args, but it worked because arg escaping was incomplete. My view is that args should be arguments passed to a program, not a shell script which only works in a particular shell.

Since lots of people were using < and > for input and output redirection, our compromise was not escaping those characters when they are alone in an arg. But other characters will be escaped so they can be passed literally to a program.

There might be another way you can get the same transformation like by doing it in your .py file. That would be platform-independent too. Not sure what are all the options that the python debugger has but maybe you can start a shell script.

@roblourens
Copy link
Member

If needed, we can continue this in #149910

@github-actions github-actions bot locked and limited conversation to collaborators Jul 2, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants