fix: disable zero-size-array min-size trick by default to eliminate UBSan violations (#249)#688
Merged
kris-jusiak merged 1 commit intoMay 27, 2026
Conversation
692ddb8 to
da3cbf5
Compare
PavelGuzenfeld
commented
May 27, 2026
| using namespace sml; | ||
|
|
||
| sm<hello_world> sm; | ||
| static_assert(1 == sizeof(sm), "sizeof(sm) != 1b"); |
Contributor
Author
There was a problem hiding this comment.
Removed due to UB.
e8652d5 to
d98b315
Compare
…BSan violations (issue boost-ext#249) The __BOOST_SML_ZERO_SIZE_ARRAY zero-length array extension placed multiple SM objects at overlapping addresses at -O2+, triggering 30+ UBSan "insufficient object size" errors on every SM that uses lambda guards or actions. MSVC and IAR already used static_assert(true) (i.e. no zero-size array) unconditionally. Clang and GCC now do the same by default. New opt-in flag: BOOST_SML_CFG_ENABLE_MIN_SIZE - Restores the old zero-size-array behaviour for users who need minimal SM object sizes and have verified UBSan clean-ness. Old opt-out flag: BOOST_SML_CFG_DISABLE_MIN_SIZE - Continues to work for backward compatibility; it takes priority over BOOST_SML_CFG_ENABLE_MIN_SIZE. test/ft/sizeof.cpp: all size assertions depend on the zero-size-array trick, so the entire file is now guarded by #if !defined(_MSC_VER) && defined(BOOST_SML_CFG_ENABLE_MIN_SIZE) test/ft/issue_249_ubsan.cpp: new regression test that exercises lambda guards and actions through a small TCP-like FSM at -O2. Verified clean with clang-18 -fsanitize=undefined,address on both C++17 and C++20. example/hello_world.cpp: remove static_assert(1 == sizeof(sm)). That assertion documented a size property that relied on the zero-size-array trick; it was never an API guarantee.
PavelGuzenfeld
added a commit
to PavelGuzenfeld/sml
that referenced
this pull request
May 27, 2026
.codacy.yml: declares C++ language for Codacy's cppcheck engine. cppcheck-project.xml: provides include search paths so cppcheck can resolve <boost/sml.hpp> without missingInclude warnings during local runs with --project=cppcheck-project.xml. References fix/issue-249-ubsan-min-size-default (PR boost-ext#688).
197742e to
a66c30c
Compare
kris-jusiak
pushed a commit
that referenced
this pull request
May 27, 2026
.codacy.yml: declares C++ language for Codacy's cppcheck engine. cppcheck-project.xml: provides include search paths so cppcheck can resolve <boost/sml.hpp> without missingInclude warnings during local runs with --project=cppcheck-project.xml. References fix/issue-249-ubsan-min-size-default (PR #688).
PavelGuzenfeld
added a commit
to PavelGuzenfeld/sml
that referenced
this pull request
May 28, 2026
PR boost-ext#688 introduced BOOST_SML_DETAIL_ZERO_SIZE_ARRAY expanding to static_assert(true) (no message) on Clang, GCC, MSVC, and IAR. The two-argument form static_assert(expr, msg) is C++11; the one-argument form static_assert(expr) is C++17. With C++14 and -Wc++17-extensions/-Werror this produces a build error. Fix: add an empty message string in all four compiler branches.
PavelGuzenfeld
added a commit
to PavelGuzenfeld/sml
that referenced
this pull request
May 28, 2026
PR boost-ext#688 introduced BOOST_SML_DETAIL_ZERO_SIZE_ARRAY expanding to static_assert(true) (no message) on Clang, GCC, MSVC, and IAR. The two-argument form static_assert(expr, msg) is C++11; the one-argument form static_assert(expr) is C++17. With C++14 and -Wc++17-extensions/-Werror this produces a build error. Fix: add an empty message string in all four compiler branches.
PavelGuzenfeld
added a commit
to PavelGuzenfeld/sml
that referenced
this pull request
May 28, 2026
PR boost-ext#688 introduced BOOST_SML_DETAIL_ZERO_SIZE_ARRAY expanding to static_assert(true) (no message) on Clang, GCC, MSVC, and IAR. The two-argument form static_assert(expr, msg) is C++11; the one-argument form static_assert(expr) is C++17. With C++14 and -Wc++17-extensions/-Werror this produces a build error. Fix: add an empty message string in all four compiler branches.
kris-jusiak
pushed a commit
that referenced
this pull request
May 28, 2026
PR #688 introduced BOOST_SML_DETAIL_ZERO_SIZE_ARRAY expanding to static_assert(true) (no message) on Clang, GCC, MSVC, and IAR. The two-argument form static_assert(expr, msg) is C++11; the one-argument form static_assert(expr) is C++17. With C++14 and -Wc++17-extensions/-Werror this produces a build error. Fix: add an empty message string in all four compiler branches.
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.
Problem
Issue #249: Clang and GCC UBSan report 30+ "insufficient object size" runtime errors at
-O2(and higher) for any SM that uses lambda guards or actions. The root cause is theBOOST_SML_DETAIL_ZERO_SIZE_ARRAYzero-length array extension used inside pool and wrapper types.At optimisation level
-O2+, the compiler sees that every struct containing a zero-length array member has zero usable bytes and may legally place multiple such objects at the same or overlapping memory addresses. UBSan then catches every dereference as an insufficient-size access.Reproducer (any TCP-like FSM with lambda guards/actions):
The existing workaround —
-DBOOST_SML_CFG_DISABLE_MIN_SIZE— has been known since the issue was filed in 2020 but forces users to discover and apply it manually.Fix
Flip the default for Clang and GCC: make the
static_assert(true)branch (no zero-length array) the default, matching what MSVC and IAR already do.BOOST_SML_CFG_ENABLE_MIN_SIZEBOOST_SML_CFG_DISABLE_MIN_SIZEENABLE_MIN_SIZEChanges
include/boost/sml.hpp: In the Clang and GCC blocks, change the condition onBOOST_SML_DETAIL_ZERO_SIZE_ARRAYfrom#if !defined(BOOST_SML_CFG_DISABLE_MIN_SIZE)→#if defined(BOOST_SML_CFG_ENABLE_MIN_SIZE) && !defined(BOOST_SML_CFG_DISABLE_MIN_SIZE)with a brief comment explaining the rationale.
test/ft/sizeof.cpp: All size assertions assume objects are zero-sized, which requires the min-size trick. Guard the entire file with#if !defined(_MSC_VER) && defined(BOOST_SML_CFG_ENABLE_MIN_SIZE).test/ft/issue_249_ubsan.cpp: New regression test — a 4-state TCP-like FSM with lambda guards and actions. Includes// cppcheck-suppress missingIncludeSystemto suppress the Codacy cppcheck false positive (the cloud runner invokes cppcheck per-file without include paths). Verified UBSan-clean withclang-18 -std=c++17 -O2 -fsanitize=undefined,addressandclang-18 -std=c++20 -O2 -fsanitize=undefined,address.example/hello_world.cpp: Removestatic_assert(1 == sizeof(sm)). The assertion documented a size property that depended on the zero-size-array trick; it was never an API guarantee. The example demonstrates correctness of transitions, guards, and actions — not object size.Verification
Clang UBSan (full ft suite, C++17 and C++20 at -O2)
GCC 14 (full suite including examples, C++20)
MSVC 19.51.36244 (C++20)
Relation
Companion CI config in PR #689 (can be merged independently in either order).
Closes #249.