Skip to content

Commit 8bd57a7

Browse files
authored
Prevent invalid scopes request from crashing debug session (#2026)
* Prevent invalid scopes request from crashing debug session If an unmapped or non-numeric frameId is sent in a scopes request, int() raises a ValueError that terminates the debug session. Wrap the scope construction in a try/except so that invalid frameIds return an empty scopes list instead, which is valid per the DAP spec. * Add logging for invalid scopes requests Log expected errors (ValueError, TypeError) at info level and unexpected exceptions with full traceback via pydev_log.exception.
1 parent bf118c8 commit 8bd57a7

2 files changed

Lines changed: 43 additions & 4 deletions

File tree

src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,10 +1109,17 @@ def on_scopes_request(self, py_db, request):
11091109
frame_id = request.arguments.frameId
11101110

11111111
variables_reference = frame_id
1112-
scopes = [
1113-
Scope("Locals", ScopeRequest(int(variables_reference), "locals"), False, presentationHint="locals"),
1114-
Scope("Globals", ScopeRequest(int(variables_reference), "globals"), False),
1115-
]
1112+
try:
1113+
scopes = [
1114+
Scope("Locals", ScopeRequest(int(variables_reference), "locals"), False, presentationHint="locals"),
1115+
Scope("Globals", ScopeRequest(int(variables_reference), "globals"), False),
1116+
]
1117+
except (ValueError, TypeError):
1118+
pydev_log.info("Failed to create scopes for frame id: %s", frame_id)
1119+
scopes = []
1120+
except Exception:
1121+
pydev_log.exception("Failed to create scopes for frame id: %s", frame_id)
1122+
scopes = []
11161123
body = ScopesResponseBody(scopes)
11171124
scopes_response = pydevd_base_schema.build_response(request, kwargs={"body": body})
11181125
return NetCommand(CMD_RETURN, 0, scopes_response, is_json=True)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
def test_on_scopes_request_with_valid_frame_id():
2+
from _pydevd_bundle._debug_adapter import pydevd_schema, pydevd_base_schema
3+
from _pydevd_bundle.pydevd_process_net_command_json import PyDevJsonCommandProcessor
4+
5+
processor = PyDevJsonCommandProcessor(pydevd_base_schema.from_json)
6+
request = pydevd_schema.ScopesRequest(pydevd_schema.ScopesArguments(frameId=1))
7+
8+
result = processor.on_scopes_request(None, request)
9+
response = result.as_dict
10+
11+
assert response["success"] is True
12+
scopes = response["body"]["scopes"]
13+
assert len(scopes) == 2
14+
assert scopes[0]["name"] == "Locals"
15+
assert scopes[0]["presentationHint"] == "locals"
16+
assert scopes[1]["name"] == "Globals"
17+
18+
19+
def test_on_scopes_request_with_invalid_frame_id():
20+
from _pydevd_bundle._debug_adapter import pydevd_schema, pydevd_base_schema
21+
from _pydevd_bundle.pydevd_process_net_command_json import PyDevJsonCommandProcessor
22+
23+
processor = PyDevJsonCommandProcessor(pydevd_base_schema.from_json)
24+
request = pydevd_schema.ScopesRequest(
25+
pydevd_schema.ScopesArguments(frameId="not_a_number")
26+
)
27+
28+
result = processor.on_scopes_request(None, request)
29+
response = result.as_dict
30+
31+
assert response["success"] is True
32+
assert response["body"]["scopes"] == []

0 commit comments

Comments
 (0)