avoid undefined behavior from UNREACHABLE on reachable code paths#7555
Draft
Goober5000 wants to merge 1 commit into
Draft
avoid undefined behavior from UNREACHABLE on reachable code paths#7555Goober5000 wants to merge 1 commit into
Goober5000 wants to merge 1 commit into
Conversation
292cebb to
d6aece4
Compare
UNREACHABLE expands to __assume(false) / __builtin_unreachable() in
release builds, which is undefined behavior if the code is ever actually
reached. Many UNREACHABLE sites only guard against unexpected-but-
possible runtime states (values from tables, mission/save files, network
packets, scripting, or user input), so reaching them should degrade
gracefully rather than invoke UB.
Replace UNREACHABLE with Assertion(false, ...) at all such sites. It
still pops an error in debug builds, but in release it is a harmless
no-op that simply falls through to the following code. Sites that are
genuinely unreachable by local invariants (e.g. a switch over a bounded
random number) are left as UNREACHABLE.
A few converted sites had no safe fall-through -- an uninitialized read,
null dereference, or null call would have followed -- so they also get a
minimal recovery: initialize the value, guard the dereference, return
early, or skip the offending item.
Where the converted site was a simple guard of the form
if (x) { Assertion(false, ...); return; }
hoist the check onto the invariant instead:
Assertion(!x, ...);
if (x) { return; }
This states the expectation directly and shows the offending value in
the debug popup, while keeping the same graceful runtime degradation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d6aece4 to
4099357
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.
UNREACHABLE expands to __assume(false) / __builtin_unreachable() in release builds, which is undefined behavior if the code is ever actually reached. Many UNREACHABLE sites only guard against unexpected-but-possible runtime states, so reaching them should degrade gracefully rather than cause undefined behavior. Replace UNREACHABLE with Assertion(false, ...) at all such sites.
A few converted sites had no safe fall-through (an uninitialized read, null dereference, or null call would have followed) so they also get a minimal recovery: initialize the value, guard the dereference, return early, or skip the offending item.
NOTE: In both FRED and QtFRED, there are several sites in sexp_tree that also need to be converted. These are deferred pending the sexp_tree refactor. This PR is in draft until then.