Skip to content

Fix rehash repair of individually corrupted shims - #3540

Open
aprylewu wants to merge 3 commits into
pyenv:masterfrom
aprylewu:fix/rehash-repair-individual-shims
Open

Fix rehash repair of individually corrupted shims#3540
aprylewu wants to merge 3 commits into
pyenv:masterfrom
aprylewu:fix/rehash-repair-individual-shims

Conversation

@aprylewu

@aprylewu aprylewu commented Sep 11, 2026

Copy link
Copy Markdown

Prerequisite

Description

rehash currently compares only the first shim against its prototype. If a later shim is overwritten (for example, printf '2\n' > "$(pyenv root)/shims/python"), it remains broken after rehashing.

Check each shim on its first registration and replace only those whose contents differ, leaving valid shims untouched. Default shims are repaired before hooks run; subsequent registrations preserve hook customizations, including the built-in sourceable shims. This includes hidden names explicitly registered by rehash hooks and dangling symlinks; unregistered dotfiles are left alone. The comparison uses a bounded Bash builtin read to avoid an external process per file and to avoid reading an accidentally overwritten large file in full. It preserves trailing newlines, rejects embedded NULs, and counts bytes consistently under Bash 3.2 with multibyte paths. The prototype comment now reflects the existing use of copies.

Checking every shim adds work: on this macOS machine, 10 alternating runs with 100 unchanged shims had median times of 55 ms before and 95 ms after; with 1,000 shims, 701 ms before and 1,300 ms after. A comparison using cmp per shim took about 311 ms for 100 shims.

Tests

  • Added regression coverage for an overwritten later shim, truncation/NUL/trailing-newline corruption, preservation of valid shim timestamps, unreadable shims, directory entries, a multibyte root path, registered hidden shims, dangling symlinks, actual activation through the built-in source hook, duplicate registration after customization, and hook invocation of an overwritten shim. Four regression tests fail against the original implementation.
  • BATS_FILE_FILTER=rehash.bats make test-unit: 25 passed, 2 skipped.
  • make test-unit: 258 passed, 8 skipped.
  • bash -n libexec/pyenv-rehash and git diff --check.

Tests ran with macOS Bash 3.2.57 and Bats 1.10.0. Skips are the fish and PowerShell integrations because those shells are unavailable. No Python installation or native extension build was performed.

AI assistance: Codex was used to implement and test this change.

@aprylewu
aprylewu requested review from a team as code owners September 11, 2026 09:12

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread libexec/pyenv-rehash Outdated
Comment thread libexec/pyenv-rehash Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread libexec/pyenv-rehash Outdated
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.

pyenv rehash fails to repair shims if one of them has been accidentally overwritten with >file

1 participant