Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 35 additions & 0 deletions 35 Lib/test/test_external_inspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,41 @@ def _extract_coroutine_stacks_lineno_only(self, stack_trace):
# ============================================================================


class TestSelfStackTrace(RemoteInspectionTestBase):
@skip_if_not_supported
@unittest.skipIf(
sys.platform == "linux" and not PROCESS_VM_READV_SUPPORTED,
"Test only runs on Linux with process_vm_readv support",
)
def test_self_trace_with_large_linetable(self):
script = textwrap.dedent("""\
import os
import _remote_debugging

assignments = "\\n".join(
f"value_{i} = {i}" for i in range(1000)
)
source = (
f"{assignments}\\n"
"_remote_debugging.RemoteUnwinder(os.getpid()).get_stack_trace()\\n"
)
code = compile(source, "large_linetable.py", "exec")
assert len(code.co_linetable) > 4096, len(code.co_linetable)
exec(code)
""")

result = subprocess.run(
[sys.executable, "-c", script],
capture_output=True,
text=True,
timeout=SHORT_TIMEOUT,
)
self.assertEqual(
result.returncode, 0,
f"stdout: {result.stdout}\nstderr: {result.stderr}"
)


@requires_remote_subprocess_debugging()
class TestGetStackTrace(RemoteInspectionTestBase):
@skip_if_not_supported
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix ``_remote_debugging`` stack traces for code objects with large line
tables.
7 changes: 5 additions & 2 deletions 7 Modules/_remote_debugging/code_objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

#include "_remote_debugging.h"

#define MAX_LINETABLE_SIZE (1024 * 1024)
#define MAX_LINETABLE_ENTRIES 65536

/* ============================================================================
* TLBC CACHING FUNCTIONS (Py_GIL_DISABLED only)
* ============================================================================ */
Expand Down Expand Up @@ -186,7 +189,6 @@ parse_linetable(const uintptr_t addrq, const char* linetable, Py_ssize_t linetab
int computed_line = firstlineno; // Running accumulator, separate from output
int val; // Temporary for varint results
uint8_t byte; // Temporary for byte reads
const size_t MAX_LINETABLE_ENTRIES = 65536;
size_t entry_count = 0;

while (ptr < end && *ptr != '\0' && entry_count < MAX_LINETABLE_ENTRIES) {
Expand Down Expand Up @@ -387,7 +389,8 @@ parse_code_object(RemoteUnwinderObject *unwinder,
}

linetable = read_py_bytes(unwinder,
GET_MEMBER(uintptr_t, code_object, unwinder->debug_offsets.code_object.linetable), 4096);
GET_MEMBER(uintptr_t, code_object, unwinder->debug_offsets.code_object.linetable),
MAX_LINETABLE_SIZE);
if (!linetable) {
set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read linetable from code object");
goto error;
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.