Skip to content

[SR-3269] UnsignedInteger.advanced(by:) & distance(to:) result in trapped overflow for UnsignedInteger values > IntMax.max #45857

@swift-ci

Description

@swift-ci
Previous ID SR-3269
Radar None
Original Reporter Jnosh (JIRA User)
Type Bug
Status Resolved
Resolution Done
Additional Detail from JIRA
Votes 0
Component/s Standard Library
Labels Bug
Assignee None
Priority Medium

md5: eb6c13d3ddfbc5d703671cbaac11a5dc

Issue Description:

The overflow is triggered regardless of the value of by or to.

Example:

// Unsigned integer > IntMax.max
let value = 0xFFFF_FFFF_FF00_0000 as UInt

// OK
let add = value + 0x1000

// Abort due to overflow
let advanced = value.advaced(by: 0x1000)

The issue lies with the default implementation for advanced & distance on UnsignedInteger (stdlib/public/core/FixedPoint.swift.gyb). The calculations are performed on intermediate IntMax values. The UnsignedInteger is cast to IntMax using numericCast() which aborts when the UnsignedInteger is larger than IntMax.max.

I can submit a pull request with a fix but I wanted to check first that this is not intended behaviour? (Probably not but I'm just surprised no one hit this case before 😛).

Also, regarding a potential fix, I see two general approaches:

  1. (Ab)Use two's complement arithmetic. Simplest but I don't know what the policy is for the Stdlib regarding binary representation. i.e. is it OK to assume two's complement?

  2. Don't cast to a signed type at all and switch on the stride's sign to decide whether to add or subtract. Would not depend on binary representation but adds a branch...

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.standard libraryArea: Standard library umbrella

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions