Repository navigation
fix(core): do not latch speedhack installed after a failed attach - #29
Merged
Merged
Conversation
…d say when Real() works speedhack::Install sets its installed flag before attaching, and left it set when the attach failed. The batch is all-or-nothing, so a failure leaves nothing installed - but the flag then made Remove() try to unwind an install that never happened, and turned any later Install into a no-op. Hand the flag back on failure so the state matches reality. Hook<Fn> claimed Real() reaches the original whether or not the slot is attached. That holds for a slot built from an address, which has one from construction, but not for one built from an export name or from the replacement alone: those have no address until an attach resolves them, and Real() is null until then. The same is true after pointing a detached slot at an export, which drops the address it had. Narrow the claim to what the code does rather than widen the code to fit the claim - nothing calls Real() on an unresolved slot today, and a slot that has not been told where its target is has nothing truthful to return. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two small correctness issues in
core, both found while auditing the hooking layer. Neither fires today; both are traps for the next caller.speedhack::Installlatched its flag on a failed attachThe flag is claimed before the attach.
AttachAllis all-or-nothing — a failed commit has Detours roll every rewritten pointer back, so nothing is installed — but the flag then said otherwise. Two consequences:Remove()passes its own CAS and callsDetachAllon eighteen slots that were never attached.Install()returns immediately, so the failure is permanent rather than retryable.Now the flag is handed back on failure, so the state matches what is actually installed.
Nothing retries
Install()today, so this is latent rather than a live bug.Hook<Fn>'sReal()contract was wider than the codeThe class comment claimed
Real()reaches the original "whether or not the slot is attached". That is true for a slot built from an address — it has one from construction — but not for the other two constructors:Hook(Target::Export(...), replacement)has no address until an attach resolves the export.explicit Hook(Fn replacement)has no target at all untilSetTarget.In both cases
Real()is null. The same applies after pointing a detached slot at an export, which drops the address it was holding — correctly, since the target moved and where is not known until the attach.I narrowed the comment rather than widening the code. A slot that has not been told where its target lives has nothing truthful to return, and inventing a fallback would hide the mistake at the call site instead of surfacing it. Nothing calls
Real()on an unresolved slot today.Verification
clang-format clean, clang-tidy clean (118 files, full no-cache run), Win32 build 0 warnings / 0 errors.
🤖 Generated with Claude Code