From ae688aa7f54d820ac7addcd080ff1c7bffbe9237 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 31 Aug 2020 14:46:23 +0200 Subject: [PATCH] fixes #15210 [backport:1.2] (#15237) * fixes #15210 [backport:1.2] * use patched version of bigints library (cherry picked from commit ff13f8cc3c74d4048b6c2604fe4b8e5365f5c13f) --- compiler/ccgexprs.nim | 43 +++++++++++++++++--------------- lib/system/chcks.nim | 3 +++ testament/important_packages.nim | 2 +- tests/misc/tunsignedconv.nim | 11 ++++++++ 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 6ed4c54b28..edb6640564 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -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: diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim index 117543fcda..25ba6f5b9b 100644 --- a/lib/system/chcks.nim +++ b/lib/system/chcks.nim @@ -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") diff --git a/testament/important_packages.nim b/testament/important_packages.nim index 5ff2ceebd3..f68735c9e3 100644 --- a/testament/important_packages.nim +++ b/testament/important_packages.nim @@ -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 diff --git a/tests/misc/tunsignedconv.nim b/tests/misc/tunsignedconv.nim index e255d9cf75..601deee0d3 100644 --- a/tests/misc/tunsignedconv.nim +++ b/tests/misc/tunsignedconv.nim @@ -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"