-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UB in <Range as Iterator>::advance_by
(Step::forward_unchecked
) for signed integers
#122420
Comments
Note that this is reachable on stable since the default impl of fn main() {
[(-128i8..127)].into_iter().flatten().nth(200);
} |
…, r=Amanieu fix unsoundness in Step::forward_unchecked for signed integers Fixes rust-lang#122420 ```rust pub fn foo(a: i8, b: u8) -> i8 { unsafe { a.checked_add_unsigned(b).unwrap_unchecked() } } ``` still compiles down to a single arithmetic instruction ([godbolt](https://rust.godbolt.org/z/qsd3xYWfE)). But we may be losing some loop optimizations if llvm can no longer easily derive that it's a finite counted loop from the no-wrapping flags.
…, r=Amanieu fix unsoundness in Step::forward_unchecked for signed integers Fixes rust-lang#122420 ```rust pub fn foo(a: i8, b: u8) -> i8 { unsafe { a.checked_add_unsigned(b).unwrap_unchecked() } } ``` still compiles down to a single arithmetic instruction ([godbolt](https://rust.godbolt.org/z/qsd3xYWfE)). But we may be losing some loop optimizations if llvm can no longer easily derive that it's a finite counted loop from the no-wrapping flags.
…, r=Amanieu fix unsoundness in Step::forward_unchecked for signed integers Fixes rust-lang#122420 ```rust pub fn foo(a: i8, b: u8) -> i8 { unsafe { a.checked_add_unsigned(b).unwrap_unchecked() } } ``` still compiles down to a single arithmetic instruction ([godbolt](https://rust.godbolt.org/z/qsd3xYWfE)). But we may be losing some loop optimizations if llvm can no longer easily derive that it's a finite counted loop from the no-wrapping flags.
Rollup merge of rust-lang#122461 - the8472:fix-step-forward-unchecked, r=Amanieu fix unsoundness in Step::forward_unchecked for signed integers Fixes rust-lang#122420 ```rust pub fn foo(a: i8, b: u8) -> i8 { unsafe { a.checked_add_unsigned(b).unwrap_unchecked() } } ``` still compiles down to a single arithmetic instruction ([godbolt](https://rust.godbolt.org/z/qsd3xYWfE)). But we may be losing some loop optimizations if llvm can no longer easily derive that it's a finite counted loop from the no-wrapping flags.
@CAD97 did you find this with Miri or just use Miri to confirm the bug? |
Only confirmed/diagnosed with Miri, spotted manually when looking at the |
I tried this code: [playground]
I expected to see this happen: No UB.
Instead, this happened: UB, confirmed by Miri.
Step::forward_unchecked(-128i8, 200usize)
is called, which does(-128i8).unchecked_add(200usize as i8)
, or(-128i8).unchecked_add(-56i8)
.The implementation of
advance_by
is correct here, andStep::forward_unchecked(-128i8, 200usize)
should be safe to call. The implementation that does a wrappingas
cast fromusize
toiN
before doing the unchecked math is the incorrect code here. Signed integers should switch to just using wrapping or unsigned math, whichever gets better codegen out of LLVM. We do havewrapping_add_unsigned
andchecked_add_unsigned
methods now, but nounchecked_add_unsigned
.Meta
rustc --version
:The text was updated successfully, but these errors were encountered: