Skip to content
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

bugs: System.Int128 operator * and % at overflow #75416

Closed
c-ohle opened this issue Sep 11, 2022 · 4 comments · Fixed by #75470
Closed

bugs: System.Int128 operator * and % at overflow #75416

c-ohle opened this issue Sep 11, 2022 · 4 comments · Fixed by #75470

Comments

@c-ohle
Copy link

c-ohle commented Sep 11, 2022

Description

In case of an overflow for multiplication * and remainder % System.Int128 gives wrong results.

All other C# integer types behave in this case correctly like standard on all machines and platforms.
The problem is that there are many algorithms that assume correct partial results in case of an overflow as part of the calculation.
All these algorithms can fail with Int128 and it's dangerous because the user wouldn't expect it.

The bug is in public static Int128 operator *(Int128 left, Int128 right)
Easy to see that the case is simply not handled and the final return new Int128(result.Upper | sign, result.Lower); copys the sign always.
This is like a proof as the sign of the result shouldn't be affected in this case.
It also follows that the error occurs in large number ranges, in other ranges not and in sub-ranges alternating.

Exactly the same issue in public static Int128 operator %(Int128 left, Int128 right).

As reference, to reproduce and test the following code can be used: Test System.Int128 functions, operator and INumber implementation.
A template solution for arbitrary number type for NET7 is used, which of course also supports int128.
An correct implementation for multiplication and remainder can be taken from there.
The tests also show that all other System.Int128 functions and operators handle the overflows correctly.

Reproduction Steps

var a = (Int128.MaxValue - 10) * +100; // -1100 ok
var b = (Int128.MaxValue - 10) * -100; // -170141183460469231731687303715884104628 wrong, should be +1100

Expected behavior

var a = (Int128.MaxValue - 10) * +100; // -1100 
var b = (Int128.MaxValue - 10) * -100; // +1100

Actual behavior

var a = (Int128.MaxValue - 10) * +100; // -1100 ok
var b = (Int128.MaxValue - 10) * -100; // -170141183460469231731687303715884104628 wrong, should be +1100

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Sep 11, 2022
@ghost
Copy link

ghost commented Sep 11, 2022

Tagging subscribers to this area: @dotnet/area-system-numerics
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

In case of an overflow for multiplication * and remainder % System.Int128 gives wrong results.

All other C# integer types behave in this case correctly like standard on all machines and platforms.
The problem is that there are many algorithms that assume correct partial results in case of an overflow as part of the calculation.
All these algorithms can fail with Int128 and it's dangerous because the user wouldn't expect it.

The bug is in public static Int128 operator *(Int128 left, Int128 right)
Easy to see that the case is simply not handled and the final return new Int128(result.Upper | sign, result.Lower); copys the sign always.
This is like a proof as the sign of the result shouldn't be affected in this case.
It also follows that the error occurs in large number ranges, in other ranges not and in sub-ranges alternating.

Exactly the same issue in public static Int128 operator %(Int128 left, Int128 right).

As reference, to reproduce and test the following code can be used: Test System.Int128 functions, operator and INumber implementation.
A template solution for arbitrary number type for NET7 is used, which of course also supports int128.
An correct implementation for multiplication and remainder can be taken from there.
The tests also show that all other System.Int128 functions and operators handle the overflows correctly.

Reproduction Steps

var a = (Int128.MaxValue - 10) * +100; // -1100 ok
var b = (Int128.MaxValue - 10) * -100; // -170141183460469231731687303715884104628 wrong, should be +1100

Expected behavior

var a = (Int128.MaxValue - 10) * +100; // -1100 
var b = (Int128.MaxValue - 10) * -100; // +1100

Actual behavior

var a = (Int128.MaxValue - 10) * +100; // -1100 ok
var b = (Int128.MaxValue - 10) * -100; // -170141183460469231731687303715884104628 wrong, should be +1100

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Author: c-ohle
Assignees: -
Labels:

area-System.Numerics

Milestone: -

@tannergooding tannergooding added bug and removed untriaged New issue has not been triaged by the area owner labels Sep 12, 2022
@tannergooding tannergooding added this to the 7.0.0 milestone Sep 12, 2022
@tannergooding tannergooding self-assigned this Sep 12, 2022
@jeffhandley
Copy link
Member

@tannergooding / @dotnet/area-system-numerics Since this is broken new functionality, I'm going to apply the blocking-release label. If the fix comes in this week, we can request servicing into RC2. Next week and beyond we'd be looking at the GA milestone.

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Sep 12, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Sep 13, 2022
@hamarb123
Copy link
Contributor

I just ran into this as well lol, I downloaded the newest daily build but I guess it wasn't new enough.

@tannergooding
Copy link
Member

Can take a couple days to be available, should be soon hopefully.

@ghost ghost locked as resolved and limited conversation to collaborators Oct 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants