fix: use checked arithmetic in bounds_check! to prevent overflow bypass#1263
Merged
ludfjig merged 1 commit intohyperlight-dev:mainfrom Feb 26, 2026
Merged
fix: use checked arithmetic in bounds_check! to prevent overflow bypass#1263ludfjig merged 1 commit intohyperlight-dev:mainfrom
ludfjig merged 1 commit intohyperlight-dev:mainfrom
Conversation
The bounds check silently wraps on usize overflow in release builds, bypassing the check entirely. Not exploitable today since callers validate offsets before reaching the macro, but any future caller that doesn't could trigger it. Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
andreiltd
approved these changes
Feb 26, 2026
jsturtevant
reviewed
Feb 26, 2026
jsturtevant
reviewed
Feb 26, 2026
jsturtevant
reviewed
Feb 26, 2026
jsturtevant
approved these changes
Feb 26, 2026
Contributor
jsturtevant
left a comment
There was a problem hiding this comment.
Making the use of our helper functions easier to do the right thing properly is 💯
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens Hyperlight host shared-memory access by making the bounds_check! macro overflow-safe, preventing usize addition wraparound from bypassing bounds checks in release builds.
Changes:
- Update
bounds_check!to usechecked_addsooffset + sizeoverflow is treated as out-of-bounds. - Add a regression test that exercises overflow offsets/sizes across several
ExclusiveSharedMemoryandHostSharedMemoryAPIs.
Comments suppressed due to low confidence (2)
src/hyperlight_host/src/mem/shared_mem.rs:57
bounds_check!is used by both read and write/copy/fill paths in this file, but the error message hard-codes "Cannot read value...". This can be misleading when the failing operation is a write or fill; consider making the message operation-agnostic (e.g., "Cannot access memory...") or allowing the call site to supply an operation label.
if $offset.checked_add($size).is_none_or(|end| end > $mem_size) {
return Err(new_error!(
"Cannot read value from offset {} with size {} in memory of size {}",
$offset,
$size,
$mem_size
));
src/hyperlight_host/src/mem/shared_mem.rs:56
bounds_check!references$offset,$size, and$mem_sizemultiple times (in the check and again in the formatted error). If a caller ever passes expressions with side effects, they could be evaluated more than once. Consider binding the macro inputs to localletvariables inside the macro expansion so each argument is evaluated exactly once.
($offset:expr, $size:expr, $mem_size:expr) => {
if $offset.checked_add($size).is_none_or(|end| end > $mem_size) {
return Err(new_error!(
"Cannot read value from offset {} with size {} in memory of size {}",
$offset,
$size,
$mem_size
dblnz
approved these changes
Feb 26, 2026
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.
The bounds check silently wraps on usize overflow in release builds, bypassing the check entirely. Not exploitable today since callers validate offsets before reaching the macro, but any future caller that doesn't could trigger it.