Skip to content

fix: canonicalize external calls in summary fixpoints - #265

Merged
SizzleUnrlsd merged 1 commit into
CoreTrace:mainfrom
sebas8866:fix/canonical-external-calls-fixpoint
Oct 20, 2026
Merged

SizzleUnrlsd merged 1 commit into
CoreTrace:mainfrom
sebas8866:fix/canonical-external-calls-fixpoint

Conversation

@sebas8866

Copy link
Copy Markdown
Contributor

c## Summary

Fix the nonterminating interprocedural summary fixpoint described in #261. When a cycle of three or more functions propagates external calls after recursive calls, the same records can rotate through insertion order on successive rounds. FunctionSummary equality compares the external-call tuple in order, so the changed flag never clears even though the analysis content has converged. This causes --check to hang indefinitely.

Reproduction

The minimal three-function cycle from issue #261 reproduces the hang with the unmodified upstream source. The new stdlib regression test invokes SummaryAnalysis in a bounded subprocess and also invokes the public python -m coretrace_python --check CLI on the synthetic cycle. Before this fix, the summary test exceeded its five-second reproduction timeout; no external calls were missing, only their tuple order was unstable.

Fix

  • Canonicalize external-call records when summarize constructs FunctionSummary, sorting by source location, caller site, invocation site, and symbol identity. This preserves the full call records and their distinct sites while making equality and caches independent of discovery history.
  • Increment CACHE_FORMAT from 16 to 17, preventing old order-dependent persistent summaries from being reused by a patched engine.
  • Add five small stdlib regression tests for fixpoint termination, CLI completion, deterministic record order, stable tie handling and old cache rejection.

Validation

  • 5/5 focused regression tests passed, using Python 3.11 in offline, read-only Docker with no network, no additional Linux capabilities, no new privileges, CPU/memory/PID limits and bounded child-process timeouts.
  • On unmodified base: the recursive test timed out after 5 seconds and the canonical order helper was absent. After the patch, the same cycle and the public --check CLI complete successfully.
  • git show --check passed; based on upstream 8b4d8a2 (0.23.0 release merge).
  • Full pytest, mypy, ruff, and pinned external regression projects were not runnable in the restricted offline environment because the dev dependencies and large external corpora were not available. Maintainer CI and broader security finding snapshots are needed before merge. Sorting may change which same-line query is reported first in some findings, as the issue discussion notes; no claim is made that all project snapshots were independently checked.

AI-assisted contribution, independently reviewed. No bounty or payment is claimed.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-17T01:44:25.689937Z 717c074 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@SizzleUnrlsd

Copy link
Copy Markdown
Contributor

Thank you for the analysis and the fix. Your commit 717c074 is now on main unchanged, with you as its author, through #268, which built on it. That is why this PR shows as merged.

#268 added three things on top of it:

  • a style commit for the three I001 import-order errors ruff check . reported in your test file, applied with ruff's own fix;
  • further tests;
  • a second part summaries: the fixpoint never terminates when a call cycle reorders external calls #261 turned out to need: the project-level loop over an import cycle did not converge either. Its members' own functions were unknown symbols on the first iteration, so the loop reached its bound on ansible and sentry even with the canonical order. The members now start from empty summaries, and the loop iterates until the summaries settle.

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.

2 participants