[IR] Verify "zeroize-stack" and !sensitive, and pin their round-trips - #5
Draft
claude[bot] wants to merge 1 commit into
Draft
[IR] Verify "zeroize-stack" and !sensitive, and pin their round-trips#5claude[bot] wants to merge 1 commit into
claude[bot] wants to merge 1 commit into
Conversation
|
|
claude
Bot
force-pushed
the
zeroize-verifier
branch
from
August 11, 2026 17:05
6637d78 to
2cc8417
Compare
The three constructs added for stack zeroization were accepted in whatever shape they were written. A malformed one was therefore not a diagnostic but a guarantee quietly reduced: an attribute naming no mode, or a mark on something that is not a stack object, reads as a request that nothing ever honors. Reject the shapes that are genuinely malformed. "zeroize-stack" selects how much of the frame is cleared, so it has to name a mode, and the attribute with no value names none. An unrecognized mode is deliberately still accepted: LangRef gives it the meaning of "used", the widest mode, so that a mode string a consumer has not learned yet widens what is cleared rather than narrows it. A verifier error there would contradict that and give up the fail-safe for nothing. Amend the LangRef sentence to say the value is required and may not be empty, which is what the check enforces, so the two now agree. !sensitive marks a stack object and its presence is the whole signal, so reject it where there is no stack object to mark, on a non-alloca instruction, on a function, on a global, and reject a payload while the contents of the node are reserved. Ignoring operands today would let IR that relies on their being ignored fix their meaning before anything wants to give them one. llvm.zeroize needs no rule of its own. Intrinsic::isSignatureValid already rejects a wrong return type, a wrong argument count, and a non-pointer or non-integer argument, and the name is remangled from the signature on load, so a check here would only restate the generic machinery. Add bitcode round-trip tests for all three. The failure worth catching is a mode string or an attachment that parses and is then lost or rewritten on reload, which downgrades the guarantee without failing, so the tests check the reloaded text against what was written, including an unrecognized mode, which has to survive verbatim, rather than only that reloading succeeds.
claude
Bot
force-pushed
the
zeroize-inlining
branch
from
August 11, 2026 19:57
055238d to
a36416f
Compare
claude
Bot
force-pushed
the
zeroize-verifier
branch
from
August 11, 2026 19:57
2cc8417 to
53f69dc
Compare
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.
Requested by Francesco Bertolaccini · Slack thread
Fifth of the wave-1 stack, based on the
zeroize-inliningbranch. Addresses trailofbits/vspells-ct-internal-notes#15.The three constructs added earlier in this stack were accepted in whatever shape they were written. A malformed one was therefore not a diagnostic but a guarantee quietly reduced: an attribute naming no mode, or a mark on something that is not a stack object, reads as a request that nothing ever honors.
Verifier rules
"zeroize-stack"selects how much of the frame is cleared, so it has to name a mode, and the attribute with no value names none. Both spellings of that, bare"zeroize-stack"and"zeroize-stack"="", are the same attribute once parsed, and both are now rejected.An unrecognized mode is deliberately still accepted. LangRef, as added in the first PR of this stack, gives it the meaning of
"used", the widest mode, so that a mode string a consumer has not learned yet widens what is cleared rather than narrows it. A verifier error there would contradict that and give up the fail-safe for nothing, so the contradiction is resolved the other way: the LangRef sentence is amended to say the value is required and may not be empty, which is exactly what the check enforces. Code and docs now agree, and the fallback survives.!sensitivemarks a stack object and its presence is the whole signal, so it is rejected where there is no stack object to mark (a non-alloca instruction, a function, a global) and rejected when the node carries a payload while its contents are reserved. Ignoring operands today would let IR that relies on their being ignored fix their meaning before anything wants to give them one.llvm.zeroizeneeds no rule of its own, and none is added.Intrinsic::isSignatureValidalready rejects a wrong return type, a wrong argument count, and a non-pointer or non-integer argument, andUpgradeIntrinsicFunctionremangles the name from the signature on load, so a check here would only restate the generic machinery.Bitcode round-trips
The failure worth catching is a mode string or an attachment that parses and is then lost or rewritten on reload: that downgrades the guarantee without anything failing. The new tests therefore check the reloaded text against what was written, and pin the second trip as a fixed point of the first, rather than only checking that reloading succeeds.
llvm/test/Bitcode/zeroize-stack-attribute.llincludes an unrecognized mode, which has to come back verbatim rather than normalized to"used".Each new test was confirmed load-bearing by breaking the implementation once and checking it fails. Notably, teaching the bitcode writer to normalize an unrecognized mode to
"used"leaves the pre-existingllvm/test/Assembler/zeroize-stack.llpassing and fails only the new bitcode test, which is the silent downgrade these tests exist for.Testing
llvm/test/Verifier(417) andllvm/test/Bitcode(318) both clean, along with the five existing tests from this stack.llvm/test/Assembler,llvm/test/Transforms/Inline,llvm/test/Transforms/DeadStoreEliminationandllvm/test/Linkershow no regressions; the seven failures there are all missing-tool artifacts of this build directory (llvm-nm,llc_dwarf) and are unrelated.AI tool use
This pull request contains AI-generated content. It was prepared with the assistance of Claude Code; the contributor has reviewed the generated code and text, is the author of the contribution, and is accountable for it, per the LLVM AI Tool Use Policy.
Generated by Claude Code