python / python/cpython

Traceback leaks global code when `exec`:ed code raises

Open
#122,071 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type-bug
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Bug report

Bug description:

Details

The traceback module's various functions for inspecting an exception leaks surrounding code when used to inspect an exception originating from an exec or eval call. I discovered this using traceback.format_exception but it applies to traceback.print_exc and the other ones that call or are called by those as well.
Specifically when compiled for "exec" mode using compile, and the exec:ed code inherits the context from which exec was called.

In this example, the comment on the first line is included in the printed traceback.

# Hi, I'm in the error message
import traceback
try:
    exec(compile("tuple()[0]", "s", "exec"))
except:
    traceback.print_exc()

This prints:

Traceback (most recent call last):
  File "<filename>", line 4, in <module>
    exec(compile("tuple()[0]", "s", "exec"))
  File "s", line 1, in <module>
    # Hi, I'm in the error message
IndexError: tuple index out of range

It seems that whatever line number the error is on in the exec:ed code is applied to the calling file instead of the exec:ed code.
Changing line 4 in the example above to exec("tuple()[0]") avoids the issue, and no info regarding the line is printed by traceback. This behavior is in line with what python outputs when the exception is not caught:

# Hi, I'm not in the error message
exec(compile("tuple()[0]", "s", "exec"))

results in:

Traceback (most recent call last):
  File "<filename>", line 2, in <module>
    exec(compile("tuple()[0]", "s", "exec"))
  File "s", line 1, in <module>
IndexError: tuple index out of range

Summary

Example code

# Hi, I'm in the error message
import traceback
try:
    exec(compile("tuple()[0]", "s", "exec"))
except:
    traceback.print_exc()
Expected behaviour

Should print the following:

Traceback (most recent call last):
  File "<filename>", line 4, in <module>
    exec(compile("tuple()[0]", "s", "exec"))
  File "s", line 1, in <module>
IndexError: tuple index out of range
Actual behaviour

Prints this:

Traceback (most recent call last):
  File "<filename>", line 4, in <module>
    exec(compile("tuple()[0]", "s", "exec"))
  File "s", line 1, in <module>
    # Hi, I'm in the error message
IndexError: tuple index out of range
CPython versions tested on:

3.8, 3.10, 3.11, 3.12

Operating systems tested on:

Linux, Windows

Linked PRs
  • gh-122126

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the example with traceback.format_exception and traceback.print_exc, comparing compiled exec code with direct exec and uncaught exceptions. Trace how traceback rendering uses the filename and line number for the exec frame; done means the expected output omits the caller's source line, including for the other traceback functions described.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.