[clang] Fix silent miscompile of template argument packs with 2^15 or more elements - #323
Open
Cfretz244 wants to merge 1 commit into
Open
[clang] Fix silent miscompile of template argument packs with 2^15 or more elements#323Cfretz244 wants to merge 1 commit into
Cfretz244 wants to merge 1 commit into
Conversation
… more elements SubstNonTypeTemplateParmPackExpr stored its argument count in a 15-bit bitfield: a pack of 32768 elements wrapped to NumArguments == 0 and the expansion produced a bogus 'excess elements in array initializer' (counts wrapping to nonzero would silently mis-size instead). Reachable from plain C++ (a 32768-element NTTP pack via make_integer_sequence); trivially reachable through std::define_static_string / reflect_constant_string, where any string of >= 32K characters forms such a pack. Also hardens the same-family narrow pack fields: - SubstNonTypeTemplateParmExpr::PackIndex (index+1 encoding) is stored full-width; the adjacent Index:15 + Final:1 pack into 16 bits, so object size is unchanged on 64-bit hosts. - SubstTemplateTypeParmTypeBitfields::PackIndex widens 15 -> 26 bits (filling the 64-bit bitfield word) with a constructor assert. - UncommonTemplateNameStorage's 15-bit Data (pack index or stored-arg count for template template packs) asserts instead of silently wrapping. Adds a regression test exercising both sides of the old cliff (define_static_string at 32767 / 32768 / 50000). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
19 tasks
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.
Fixes #321.
A template argument pack of 2^15 or more elements silently miscompiled:
SubstNonTypeTemplateParmPackExprstored its argument count in a 15-bit bitfield, so a 32768-element pack wrapped toNumArguments == 0and the expansion produced a bogus "excess elements in array initializer" (nonzero wraps would silently mis-size). Reachable from plain C++ (a 32768-element NTTP pack viamake_integer_sequence); trivially reachable throughstd::define_static_string/reflect_constant_string, where any lifted string of 32K+ characters forms such a pack.Changes:
SubstNonTypeTemplateParmPackExpr::NumArgumentsstored full-width (the adjacentIndex/Finalbitfields still pack into 16 bits).SubstNonTypeTemplateParmExpr::PackIndex(index+1 encoding) full-width at no object-size cost on 64-bit hosts.SubstTemplateTypeParmTypeBitfields::PackIndexwidened 15 → 26 bits (fills the 64-bit bitfield word) + constructor assert.UncommonTemplateNameStorage's 15-bitData(pack index or stored-arg count for template template packs) asserts instead of silently wrapping.libcxx/test/std/experimental/reflection/define-static-string-large.pass.cppexercising both sides of the old cliff (32767 / 32768 / 50000 round-trips).Validated on a Release+assertions AArch64/macOS build of this branch: both repros (reflection + plain C++) fail at the base commit and pass with the fix;
clang/test/Reflectionparity with base; additionally exercised by a 36-library reflection-driven binding-generation corpus.Note for upstream-of-upstream: the narrow fields exist in
llvm/llvm-projecttoo, and the plain-C++ repro should reproduce there — reflection merely makes 32K+ packs easy to form. May be worth forwarding.