Skip to content

Commit 08d51e5

Browse files
authored
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
1 parent 5b5cd7f commit 08d51e5

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

compiler/transf.nim

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,34 @@ proc transformConv(c: PTransf, n: PNode): PNode =
552552
# we don't include uint and uint64 here as these are no ordinal types ;-)
553553
if not isOrdinalType(source):
554554
# float -> int conversions. ugh.
555-
result = transformSons(c, n)
555+
# generate a range check:
556+
if dest.kind in tyInt..tyInt64:
557+
if dest.kind == tyInt64 or source.kind == tyInt64:
558+
result = newTransNode(nkChckRange64, n, 3)
559+
else:
560+
result = newTransNode(nkChckRange, n, 3)
561+
dest = skipTypes(n.typ, abstractVar)
562+
563+
if dest.size < source.size:
564+
let intType =
565+
if source.size == 4:
566+
getSysType(c.graph, n.info, tyInt32)
567+
else:
568+
getSysType(c.graph, n.info, tyInt64)
569+
result[0] =
570+
newTreeIT(n.kind, n.info, n.typ, n[0],
571+
newTreeIT(nkConv, n.info, intType,
572+
newNodeIT(nkType, n.info, intType), transform(c, n[1]))
573+
)
574+
575+
else:
576+
result[0] = transformSons(c, n)
577+
578+
result[1] = newIntTypeNode(firstOrd(c.graph.config, dest), dest)
579+
result[2] = newIntTypeNode(lastOrd(c.graph.config, dest), dest)
580+
else:
581+
result = transformSons(c, n)
582+
556583
elif firstOrd(c.graph.config, n.typ) <= firstOrd(c.graph.config, n[1].typ) and
557584
lastOrd(c.graph.config, n[1].typ) <= lastOrd(c.graph.config, n.typ):
558585
# BUGFIX: simply leave n as it is; we need a nkConv node,

tests/stdlib/tsystem.nim

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,32 @@ proc bar2() =
245245

246246
static: bar2()
247247
bar2()
248+
249+
when not defined(js):
250+
proc foo =
251+
block:
252+
var s1:int = -10
253+
doAssertRaises(RangeDefect):
254+
var n2:Natural = s1.Natural
255+
256+
block:
257+
var f = 751.0
258+
let m = f.int8
259+
260+
block:
261+
var s2:float = -10
262+
doAssertRaises(RangeDefect):
263+
var n2:Natural = s2.Natural
264+
265+
266+
block:
267+
type A = range[0..10]
268+
269+
let f = 156.0
270+
271+
doAssertRaises(RangeDefect):
272+
let a = f.A
273+
274+
echo a # 156
275+
276+
foo()

0 commit comments

Comments
 (0)