FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(ctracer): handle edge-case exceptions in tracer.c to prevent cras… by dynapx · Pull Request #2219 · coveragepy/coveragepy · GitHub

fix(ctracer): handle edge-case exceptions in tracer.c to prevent cras… - #2219

Open
dynapx wants to merge 1 commit into
coveragepy:mainfrom
dynapx:fix-tracer-c-api-contracts
Open

fix(ctracer): handle edge-case exceptions in tracer.c to prevent cras…#2219
dynapx wants to merge 1 commit into
coveragepy:mainfrom
dynapx:fix-tracer-c-api-contracts

Conversation

dynapx commented Jul 6, 2026

Copy link
Copy Markdown

Description

Hi there! 👋

During a code robustness audit using a static analysis tool tailored for Python C-API contracts, we identified two edge-case missing exception checks in coverage/ctracer/tracer.c that could lead to interpreter crashes or SystemError under specific conditions.

This PR addresses both issues to ensure graceful exception propagation.

1. Potential Null Pointer Dereference in Tracer_call

Issue:
In Tracer_call, there is a comment noting: /* In Python, the what argument is a string, we need to find an int for the C function. */. While it is true that under normal execution, sys.settrace will only pass standard ASCII event names (like "call", "return"), the tracer object itself is exposed to the Python user space and can be invoked directly (e.g., tracer_instance(frame, "non_ascii_string", arg)).

If a non-ASCII string is passed (or if extreme memory allocation fails), PyUnicode_AsASCIIString(what_str) returns NULL and sets a UnicodeEncodeError. Currently, this NULL return is blindly consumed by PyBytes_AS_STRING() and Py_DECREF(), triggering a deterministic Segmentation Fault.

Why this matters (CI Resilience & Supply Chain):
As coverage.py is a foundational tool in almost every Python CI/CD pipeline, resilience against malformed inputs is critical. In modern complex test suites, a rogue mock, a buggy third-party plugin, or a compromised package in the software supply chain could inadvertently (or maliciously) feed poisoned data to the tracer callbacks. A Segmentation Fault immediately kills the CI worker process without any Python traceback, making debugging a nightmare for developers.

Fix:
By adding a simple NULL check before macro expansion, we ensure that the boundary between C and Python remains robust. If an invalid string is passed, the C-extension now safely steps back (goto done) and propagates the UnicodeEncodeError, allowing the test suite to fail gracefully with a readable traceback.

2. Tri-state Boolean Confusion and Transactional State Tearing in CTracer_start

Issue:
In CTracer_start, the evaluation of trace_arcs uses PyObject_IsTrue() embedded in a C logical && expression.
According to the C-API contract, PyObject_IsTrue() returns -1 on error. However, C's logical && evaluates -1 as true. This causes:

  1. State corruption: tracing_arcs is incorrectly set to 1.
  2. Exception suppression: Returning a non-NULL pointer (PyObject *)self with an active exception forces a generic SystemError.
  3. State tearing: Since PyEval_SetTrace is called before the evaluation, if an exception were correctly propagated, the interpreter would have a tracer set but atomic_store(&self->started, TRUE) would be skipped, leaving the internal state machine corrupted.

Fix:
We hoisted the PyObject_IsTrue() evaluation before any state mutations (i.e., PyEval_SetTrace and atomic_store). If it returns -1, we immediately return NULL to safely propagate the exception while ensuring transactional atomicity of the object's state.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant


Back | FazBrowse Home | New Git URL