Skip to content

Overflow in libstd/io/cursor.rs "seek" returns incorrect error with large positions #39631

Closed
@amosonn

Description

@amosonn

Seems to be a reroll #20678. I have some idea how to fix it, will try to draft a pull request later, but it basically requires checking the sign of the i64, negging if required and casting to u64, and using checked_add or checked_sub.

I will divide into cases to demonstrate that this is required, to save repeating phrases, I will use the following notation:
S means pos < i64::max_value(), L means pos > i64::max_value();
P means n >= 0, N means n < 0;
O+ means we will notice bads by checking OF on add (u64::checked_add), O- means we will notice them by checking OF on sub (u64::checked_sub after i64::wrapping_neg), Z+ means we will notice by adding as i64 and making sure result is non-negative, Z- is making sure it is negative, D+ mean we will notice bads by asserting OF is set on add (u64::overflowing_add), D- is likewise for sub (u64::overflowing_sub). Note the we don't need to consider n == i64::min_value(), because after i64::wrapping_neg and as u64 we still get the right, large, positive number.
So, we have the following cases and appropriate checks that spot trouble:

  • SP -> O+Z+D- (there's never a problem, but the others false-positive)
  • LP -> O+Z-D- (but D- requires also that the result is non-zero).
  • SN -> O-Z+D+
  • LN -> O-D+ (there's never a problem, but the others false-positive)

Overall, we see that there is no one test which works for all cases, and a minimum of two cases (and tests) yields the solution described above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions