Skip to content

gh-131591: Implement PEP 768 #131592

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

Closed
wants to merge 39 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6f6b4cd
gh-131591: Implement PEP 768
pablogsal Mar 22, 2025
9b86022
Add tests and use io.open_code
pablogsal Mar 23, 2025
af84100
Some fixes
pablogsal Mar 23, 2025
19ef7ae
Prepare for windows support
pablogsal Mar 24, 2025
444453c
Update windows files
pablogsal Mar 24, 2025
1d3ad3c
Fix syntax error
ivonastojanovic Mar 25, 2025
eeec1f6
Merge pull request #97 from ivonastojanovic/fix_windows_files
pablogsal Mar 25, 2025
fd993e3
Locate PyRuntime on Windows
ivonastojanovic Mar 27, 2025
96798c3
Read process memory on Windows
ivonastojanovic Mar 27, 2025
075ca65
Write to process memory on Windows
ivonastojanovic Mar 27, 2025
45e73c5
Prevent attaching to a process with a different architecture
ivonastojanovic Mar 28, 2025
ed2f325
Revert "Prevent attaching to a process with a different architecture"
godlygeek Mar 28, 2025
6076548
Merge pull request #98 from ivonastojanovic/external_debugger_windows…
godlygeek Mar 28, 2025
a9d3ea9
Remove unused struct member
godlygeek Mar 28, 2025
e235e62
Set an explicit size for a struct member
godlygeek Mar 28, 2025
d51dda0
Revert an accidental whitespace change
godlygeek Mar 28, 2025
38a4d51
Factor running a debugger script into a helper function
godlygeek Mar 28, 2025
a98898d
Harden remote debugging integration
godlygeek Mar 28, 2025
997b557
Use _fdopen to open the debugger script on Windows
godlygeek Mar 28, 2025
f6dec59
Ensure the debugger script is always closed
godlygeek Mar 28, 2025
d273c5b
Fix incorrect docstring
godlygeek Mar 29, 2025
c9a2146
Document restrictions for remote_exec
godlygeek Mar 29, 2025
4af1744
Simplify handling of Windows paths
godlygeek Mar 29, 2025
5c0b8b9
Make remote_exec accept `bytes` paths
godlygeek Mar 29, 2025
c8779cd
Refactor to avoid duplicate error handling
godlygeek Mar 26, 2025
6889042
Check for debug offset compatibility before using the offsets
godlygeek Mar 26, 2025
7f7aa8b
Give a some variables shorter names
godlygeek Mar 26, 2025
fbecfdb
Have read_memory/write_memory return 0 on success
godlygeek Mar 27, 2025
fa98f64
Improve an error message
godlygeek Mar 27, 2025
5b4cb00
Remove a debugging printf
godlygeek Mar 29, 2025
0dd7797
Fix a remote read to use the correct type
godlygeek Mar 29, 2025
b8a0503
Improve the error message when we can't find the requested thread
godlygeek Mar 29, 2025
9344d1d
Remove a useless check
godlygeek Mar 29, 2025
9368d38
Only accept a flag of 1 to mean remote debugging is enabled
godlygeek Mar 29, 2025
166f4d6
Merge remote-tracking branch 'upstream/main'
pablogsal Mar 31, 2025
d253966
Lint
pablogsal Mar 31, 2025
8e04fdd
simplify socket handling
pablogsal Mar 31, 2025
0c2b275
Add NEWS entry
pablogsal Mar 31, 2025
80856d3
Add more docs
pablogsal Mar 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Factor running a debugger script into a helper function
  • Loading branch information
godlygeek committed Mar 29, 2025
commit 38a4d51f679e5bed68de3396c91a26e50f9ef532
118 changes: 66 additions & 52 deletions Python/ceval_gil.c
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,71 @@ _PyEval_DisableGIL(PyThreadState *tstate)
}
#endif

#ifdef Py_REMOTE_DEBUG
// Note that this function is inline to avoid creating a PLT entry
// that would be an easy target for a ROP gadget.
static inline void run_remote_debugger_script(const char *path)
{
if (0 != PySys_Audit("remote_debugger_script", "s", path)) {
PyErr_FormatUnraisable("Error when auditing remote debugger script %s", path);
return;
}

// Open the debugger script with the open code hook. Unfortunately this forces us to handle
// the resulting Python object, which is a file object and therefore we need to call
// Python methods on it instead of the simpler C equivalents.
PyObject* fileobj = PyFile_OpenCode(path);
if (!fileobj) {
PyErr_FormatUnraisable("Error when opening debugger script %s", path);
return;
}

#ifdef MS_WINDOWS
PyObject* path_obj = PyUnicode_FromString(path);
if (!path_obj) {
PyErr_FormatUnraisable("Error when converting remote debugger script path %s to Unicode", path);
return;
}
wchar_t* wpath = PyUnicode_AsWideCharString(path_obj, NULL);
Py_DECREF(path_obj);
if (!wpath) {
PyErr_FormatUnraisable("Error when converting remote debugger script path %s to wide char", path);
return;
}
FILE* f = _wfopen(wpath, L"r");
#else
int fd = PyObject_AsFileDescriptor(fileobj);
if (fd == -1) {
PyErr_FormatUnraisable("Error when getting file descriptor for debugger script %s", path);
return;
}
FILE* f = fdopen(fd, "r");
#endif

if (!f) {
PyErr_SetFromErrno(PyExc_OSError);
} else {
PyRun_AnyFile(f, path);
}

#ifdef MS_WINDOWS
PyMem_Free(wpath);
fclose(f);
#endif

if (PyErr_Occurred()) {
PyErr_FormatUnraisable("Error executing debugger script %s", path);
}

PyObject* res = PyObject_CallMethod(fileobj, "close", "");
if (!res) {
PyErr_FormatUnraisable("Error when closing debugger script %s", path);
} else {
Py_DECREF(res);
}
Py_DECREF(fileobj);
}
#endif

/* Do periodic things, like check for signals and async I/0.
* We need to do reasonably frequently, but not too frequently.
Expand Down Expand Up @@ -1327,58 +1392,7 @@ _Py_HandlePending(PyThreadState *tstate)
tstate->remote_debugger_support.debugger_pending_call = 0;
const char *path = tstate->remote_debugger_support.debugger_script_path;
if (*path) {
if (0 != PySys_Audit("remote_debugger_script", "s", path)) {
PyErr_FormatUnraisable("Error when auditing remote debugger script %s", path);
} else {
// Open the debugger script with the open code hook. Unfortunately this forces us to handle
// the resulting Python object, which is a file object and therefore we need to call
// Python methods on it instead of the simpler C equivalents.
PyObject* fileobj = PyFile_OpenCode(path);
if (!fileobj) {
PyErr_FormatUnraisable("Error when opening debugger script %s", path);
return 0;
}
#ifdef MS_WINDOWS
PyObject* path_obj = PyUnicode_FromString(path);
if (!path_obj) {
PyErr_FormatUnraisable("Error when converting remote debugger script path %s to Unicode", path);
return 0;
}
wchar_t* wpath = PyUnicode_AsWideCharString(path_obj, NULL);
Py_DECREF(path_obj);
if (!wpath) {
PyErr_FormatUnraisable("Error when converting remote debugger script path %s to wide char", path);
return 0;
}
FILE* f = _wfopen(wpath, L"r");
#else
int fd = PyObject_AsFileDescriptor(fileobj);
if (fd == -1) {
PyErr_FormatUnraisable("Error when getting file descriptor for debugger script %s", path);
return 0;
}
FILE* f = fdopen(fd, "r");
#endif
if (!f) {
PyErr_SetFromErrno(PyExc_OSError);
} else {
PyRun_AnyFile(f, path);
}
#ifdef MS_WINDOWS
PyMem_Free(wpath);
fclose(f);
#endif
if (PyErr_Occurred()) {
PyErr_FormatUnraisable("Error executing debugger script %s", path);
}
PyObject* res = PyObject_CallMethod(fileobj, "close", "");
if (!res) {
PyErr_FormatUnraisable("Error when closing debugger script %s", path);
} else {
Py_DECREF(res);
}
Py_DECREF(fileobj);
}
run_remote_debugger_script(path);
}
}
}
Expand Down