fixes #15210 [backport:1.2] (#15237)

* fixes #15210 [backport:1.2]

* use patched version of bigints library

(cherry picked from commit ff13f8cc3c)
This commit is contained in:
Andreas Rumpf
2020-08-31 14:46:23 +02:00
committed by narimiran
parent 4e428c5a18
commit ae688aa7f5
4 changed files with 38 additions and 21 deletions

View File

@@ -1981,25 +1981,30 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc) =
checkUnsignedConversions notin p.config.legacyFeatures):
discard "no need to generate a check because it was disabled"
else:
let raiser =
case skipTypes(n.typ, abstractVarRange).kind
of tyUInt..tyUInt64, tyChar: "raiseRangeErrorU"
of tyFloat..tyFloat128: "raiseRangeErrorF"
else: "raiseRangeErrorI"
discard cgsym(p.module, raiser)
# This seems to be bug-compatible with Nim version 1 but what we
# should really do here is to check if uint64Value < high(int)
let n0t = n[0].typ
let boundaryCast =
if n0t.skipTypes(abstractVarRange).kind in {tyUInt, tyUInt32, tyUInt64} or
(n0t.sym != nil and sfSystemModule in n0t.sym.owner.flags and n0t.sym.name.s == "csize"):
"(NI64)"
else:
""
# emit range check:
linefmt(p, cpsStmts, "if ($6($1) < $2 || $6($1) > $3){ $4($1, $2, $3); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), boundaryCast])
if n0t.kind in {tyUInt, tyUInt64}:
linefmt(p, cpsStmts, "if ($1 > ($6)($3)){ #raiseRangeErrorNoArgs(); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), getTypeDesc(p.module, n0t)])
else:
let raiser =
case skipTypes(n.typ, abstractVarRange).kind
of tyUInt..tyUInt64, tyChar: "raiseRangeErrorU"
of tyFloat..tyFloat128: "raiseRangeErrorF"
else: "raiseRangeErrorI"
discard cgsym(p.module, raiser)
let boundaryCast =
if n0t.skipTypes(abstractVarRange).kind in {tyUInt, tyUInt32, tyUInt64} or
(n0t.sym != nil and sfSystemModule in n0t.sym.owner.flags and n0t.sym.name.s == "csize"):
"(NI64)"
else:
""
linefmt(p, cpsStmts, "if ($6($1) < $2 || $6($1) > $3){ $4($1, $2, $3); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), boundaryCast])
putIntoDest(p, d, n, "(($1) ($2))" %
[getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage)
@@ -2665,9 +2670,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
expr(p, n[1][0], d)
of nkObjDownConv: downConv(p, n, d)
of nkObjUpConv: upConv(p, n, d)
of nkChckRangeF: genRangeChck(p, n, d)
of nkChckRange64: genRangeChck(p, n, d)
of nkChckRange: genRangeChck(p, n, d)
of nkChckRangeF, nkChckRange64, nkChckRange: genRangeChck(p, n, d)
of nkStringToCString: convStrToCStr(p, n, d)
of nkCStringToString: convCStrToStr(p, n, d)
of nkLambdaKinds:

View File

@@ -38,6 +38,9 @@ proc raiseRangeErrorU(i, a, b: uint64) {.compilerproc, noinline.} =
# todo: better error reporting
sysFatal(RangeError, "value out of range")
proc raiseRangeErrorNoArgs() {.compilerproc, noinline.} =
sysFatal(RangeDefect, "value out of range")
proc raiseObjectConversionError() {.compilerproc, noinline.} =
sysFatal(ObjectConversionError, "invalid object conversion")

View File

@@ -9,7 +9,7 @@ pkg "argparse"
pkg "arraymancer", true, "nim c tests/tests_cpu.nim"
pkg "ast_pattern_matching", false, "nim c -r --oldgensym:on tests/test1.nim"
pkg "asyncmysql", true
pkg "bigints"
pkg "bigints", url = "https://github.com/Araq/nim-bigints"
pkg "binaryheap", false, "nim c -r binaryheap.nim"
# pkg "blscurve", true # pending https://github.com/status-im/nim-blscurve/issues/39
pkg "bncurve", true

View File

@@ -75,3 +75,14 @@ let rangeVar = 0'u64 ..< limit
doAssert repr(rangeVar) == """[a = 0,
b = 0]
"""
# bug #15210
let a3 = not 0'u64
var success = false
try:
discard a3.int64
except RangeDefect:
success = true
doAssert success, "conversion should fail at runtime"