Skip to content

UB in <Range as Iterator>::advance_by (Step::forward_unchecked) for signed integers #122420

Closed
@CAD97

Description

@CAD97

I tried this code: [playground]

#![feature(iter_advance_by)]

fn main() {
    _ = (-128i8..127).advance_by(200);
}

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, and Step::forward_unchecked(-128i8, 200usize) should be safe to call. The implementation that does a wrapping as cast from usize to iN 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 have wrapping_add_unsigned and checked_add_unsigned methods now, but no unchecked_add_unsigned.

Meta

rustc --version:

rustc 1.78.0-nightly (2024-03-12 a165f1f65015b1bd4afd)

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-libsRelevant to the library team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions