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

TypeSystemAstBuilder.FractionApprox() will overflow for special double value on debug builds of ILSpy #2615

Closed
yyjdelete opened this issue Jan 25, 2022 · 1 comment
Labels

Comments

@yyjdelete
Copy link
Contributor

Not sure if it's an actual issue, it only happen on debug builds of ILSpy.

Steps to reproduce

double Z => 1D / long.MaxValue;

Error message shown

For debug builds only

System.OverflowException: 
   at ICSharpCode.Decompiler.CSharp.Syntax.TypeSystemAstBuilder.FractionApprox(Double value, Int32 maxDenominator) in TypeSystemAstBuilder.cs:line 1585
   at ICSharpCode.Decompiler.CSharp.Syntax.TypeSystemAstBuilder.ConvertFloatingPointLiteral(IType type, Object constantValue) in TypeSystemAstBuilder.cs:line 1379
   at ICSharpCode.Decompiler.CSharp.Syntax.TypeSystemAstBuilder.ConvertConstantValue(IType expectedType, IType type, Object constantValue) in TypeSystemAstBuilder.cs:line 1038
   at ICSharpCode.Decompiler.CSharp.Syntax.TypeSystemAstBuilder.ConvertConstantValue(IType type, Object constantValue) in TypeSystemAstBuilder.cs:line 975
   at ICSharpCode.Decompiler.CSharp.ExpressionBuilder.VisitLdcF8(LdcF8 inst, TranslationContext context) in ExpressionBuilder.cs:line 599
   at ICSharpCode.Decompiler.IL.LdcF8.AcceptVisitor[C,T](ILVisitor`2 visitor, C context) in Instructions.cs:line 2979
   at ICSharpCode.Decompiler.CSharp.ExpressionBuilder.Translate(ILInstruction inst, IType typeHint) in ExpressionBuilder.cs:line 161
   at ICSharpCode.Decompiler.CSharp.StatementBuilder.VisitLeave(Leave inst) in StatementBuilder.cs:line 383
   at ICSharpCode.Decompiler.IL.Leave.AcceptVisitor[T](ILVisitor`1 visitor) in Instructions.cs:line 1316
   at ICSharpCode.Decompiler.CSharp.StatementBuilder.Convert(ILInstruction inst) in StatementBuilder.cs:line 78
   at ICSharpCode.Decompiler.CSharp.StatementBuilder.ConvertBlockContainer(BlockStatement blockStatement, BlockContainer container, IEnumerable`1 blocks, Boolean isLoop) in StatementBuilder.cs:line 1398
   at ICSharpCode.Decompiler.CSharp.StatementBuilder.ConvertBlockContainer(BlockContainer container, Boolean isLoop) in StatementBuilder.cs:line 1328
   at ICSharpCode.Decompiler.CSharp.StatementBuilder.VisitBlockContainer(BlockContainer container) in StatementBuilder.cs:line 1214
   at ICSharpCode.Decompiler.IL.BlockContainer.AcceptVisitor[T](ILVisitor`1 visitor) in Instructions.cs:line 847
   at ICSharpCode.Decompiler.CSharp.StatementBuilder.Convert(ILInstruction inst) in StatementBuilder.cs:line 78
   at ICSharpCode.Decompiler.CSharp.StatementBuilder.ConvertAsBlock(ILInstruction inst) in StatementBuilder.cs:line 83
   at ICSharpCode.Decompiler.CSharp.CSharpDecompiler.DecompileBody(IMethod method, EntityDeclaration entityDecl, DecompileRun decompileRun, ITypeResolveContext decompilationContext) in CSharpDecompiler.cs:line 1574

Details

  • Product in use: ILSpy
  • Version in use: 7.2.0.6825-preview4(Debug)
@yyjdelete yyjdelete added the Bug label Jan 25, 2022
@dgrunwald
Copy link
Member

Ah, that's an interesting constant: 1 / (double)long.MaxValue
The (double) cast involves loss of precision: long.MaxValue is rounded up to long.MaxValue+1, which is a power of two.
The division then is exact, resulting in the double 0x3c00000000000000.

When trying to represent this as a fraction, we get long.MaxValue+1 as divisor, which does not fit type long, but compares equal to (not greater than!) long.MaxValue because the long->double conversion involved in a some_double > long.MaxValue comparison has the same loss of precision.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants