From 8616161cc4f105690dea4d085214ae28fd8a7e45 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Sat, 19 Jul 2025 03:30:50 +0800 Subject: [PATCH] fixes #7179; Floats are not range checked (#25050) fixes #7179 ```nim var f = 751.0 echo f.int8 ``` In this case, `int8(float)` yields different numbers for different optimization levels, since float to int conversions are undefined behaviors. In this PR, it mitigates this problem by conversions to same size integers before converting to the final type: i.e. `int8(int64(float))`, which has UB problems but is better than before (cherry picked from commit 08d51e5c881e7d2d0c192832c3a235cb6a3be425) --- compiler/transf.nim | 29 ++++++++++++++++++++++++++++- tests/stdlib/tsystem.nim | 29 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/compiler/transf.nim b/compiler/transf.nim index a2090af841..0ed2e10e82 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -552,7 +552,34 @@ proc transformConv(c: PTransf, n: PNode): PNode = # we don't include uint and uint64 here as these are no ordinal types ;-) if not isOrdinalType(source): # float -> int conversions. ugh. - result = transformSons(c, n) + # generate a range check: + if dest.kind in tyInt..tyInt64: + if dest.kind == tyInt64 or source.kind == tyInt64: + result = newTransNode(nkChckRange64, n, 3) + else: + result = newTransNode(nkChckRange, n, 3) + dest = skipTypes(n.typ, abstractVar) + + if dest.size < source.size: + let intType = + if source.size == 4: + getSysType(c.graph, n.info, tyInt32) + else: + getSysType(c.graph, n.info, tyInt64) + result[0] = + newTreeIT(n.kind, n.info, n.typ, n[0], + newTreeIT(nkConv, n.info, intType, + newNodeIT(nkType, n.info, intType), transform(c, n[1])) + ) + + else: + result[0] = transformSons(c, n) + + result[1] = newIntTypeNode(firstOrd(c.graph.config, dest), dest) + result[2] = newIntTypeNode(lastOrd(c.graph.config, dest), dest) + else: + result = transformSons(c, n) + elif firstOrd(c.graph.config, n.typ) <= firstOrd(c.graph.config, n[1].typ) and lastOrd(c.graph.config, n[1].typ) <= lastOrd(c.graph.config, n.typ): # BUGFIX: simply leave n as it is; we need a nkConv node, diff --git a/tests/stdlib/tsystem.nim b/tests/stdlib/tsystem.nim index 343021bd3d..dc2163f242 100644 --- a/tests/stdlib/tsystem.nim +++ b/tests/stdlib/tsystem.nim @@ -238,3 +238,32 @@ proc bar2() = static: bar2() bar2() + +when not defined(js): + proc foo = + block: + var s1:int = -10 + doAssertRaises(RangeDefect): + var n2:Natural = s1.Natural + + block: + var f = 751.0 + let m = f.int8 + + block: + var s2:float = -10 + doAssertRaises(RangeDefect): + var n2:Natural = s2.Natural + + + block: + type A = range[0..10] + + let f = 156.0 + + doAssertRaises(RangeDefect): + let a = f.A + + echo a # 156 + + foo()