Merge pull request #9881 from timotheecour/pr_ref_9880
refs #9880 show index and bound in lots of `index out of bounds` errors
This commit is contained in:
commit
bb1ce398af
9 changed files with 64 additions and 23 deletions
|
|
@ -866,15 +866,15 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||||
# semantic pass has already checked for const index expressions
|
# semantic pass has already checked for const index expressions
|
||||||
if firstOrd(p.config, ty) == 0:
|
if firstOrd(p.config, ty) == 0:
|
||||||
if (firstOrd(p.config, b.t) < firstOrd(p.config, ty)) or (lastOrd(p.config, b.t) > lastOrd(p.config, ty)):
|
if (firstOrd(p.config, b.t) < firstOrd(p.config, ty)) or (lastOrd(p.config, b.t) > lastOrd(p.config, ty)):
|
||||||
linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n",
|
linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError2($1, $2);$n",
|
||||||
rdCharLoc(b), intLiteral(lastOrd(p.config, ty)))
|
rdCharLoc(b), intLiteral(lastOrd(p.config, ty)))
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
|
linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError3($1, $2, $3);$n",
|
||||||
rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty)))
|
rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty)))
|
||||||
else:
|
else:
|
||||||
let idx = getOrdValue(y)
|
let idx = getOrdValue(y)
|
||||||
if idx < firstOrd(p.config, ty) or idx > lastOrd(p.config, ty):
|
if idx < firstOrd(p.config, ty) or idx > lastOrd(p.config, ty):
|
||||||
localError(p.config, x.info, "index out of bounds")
|
localError(p.config, x.info, formatErrorIndexBound(idx, firstOrd(p.config, ty), lastOrd(p.config, ty)))
|
||||||
d.inheritLocation(a)
|
d.inheritLocation(a)
|
||||||
putIntoDest(p, d, n,
|
putIntoDest(p, d, n,
|
||||||
ropecg(p.module, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage)
|
ropecg(p.module, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage)
|
||||||
|
|
@ -913,7 +913,7 @@ proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, x, a)
|
initLocExpr(p, x, a)
|
||||||
initLocExpr(p, y, b) # emit range check:
|
initLocExpr(p, y, b) # emit range check:
|
||||||
if optBoundsCheck in p.options:
|
if optBoundsCheck in p.options:
|
||||||
linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError();$n",
|
linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError2($1,$2Len_0-1);$n",
|
||||||
rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``!
|
rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``!
|
||||||
inheritLocation(d, a)
|
inheritLocation(d, a)
|
||||||
putIntoDest(p, d, n,
|
putIntoDest(p, d, n,
|
||||||
|
|
@ -929,11 +929,11 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||||
if optBoundsCheck in p.options:
|
if optBoundsCheck in p.options:
|
||||||
if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options):
|
if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options):
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
"if ((NU)($1) > (NU)$2) #raiseIndexError();$n",
|
"if ((NU)($1) > (NU)$2) #raiseIndexError2($1,$2);$n",
|
||||||
rdLoc(b), lenExpr(p, a))
|
rdLoc(b), lenExpr(p, a))
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
"if ((NU)($1) >= (NU)$2) #raiseIndexError();$n",
|
"if ((NU)($1) >= (NU)$2) #raiseIndexError2($1,$2-1);$n",
|
||||||
rdLoc(b), lenExpr(p, a))
|
rdLoc(b), lenExpr(p, a))
|
||||||
if d.k == locNone: d.storage = OnHeap
|
if d.k == locNone: d.storage = OnHeap
|
||||||
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ import
|
||||||
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
|
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
|
||||||
lowerings, tables, sets, ndi, lineinfos, pathutils, transf
|
lowerings, tables, sets, ndi, lineinfos, pathutils, transf
|
||||||
|
|
||||||
|
import system/helpers2
|
||||||
|
|
||||||
when not defined(leanCompiler):
|
when not defined(leanCompiler):
|
||||||
import semparallel
|
import semparallel
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ import
|
||||||
nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
|
nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
|
||||||
commands, magicsys, modulegraphs, strtabs, lineinfos
|
commands, magicsys, modulegraphs, strtabs, lineinfos
|
||||||
|
|
||||||
|
import system/helpers2
|
||||||
|
|
||||||
proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||||
case skipTypes(n.typ, abstractVarRange).kind
|
case skipTypes(n.typ, abstractVarRange).kind
|
||||||
of tyInt:
|
of tyInt:
|
||||||
|
|
@ -489,11 +491,11 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
result = x.sons[int(idx)]
|
result = x.sons[int(idx)]
|
||||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||||
else:
|
else:
|
||||||
localError(g.config, n.info, "index out of bounds: " & $n)
|
localError(g.config, n.info, formatErrorIndexBound(idx, sonsLen(x)+1) & $n)
|
||||||
of nkBracket:
|
of nkBracket:
|
||||||
idx = idx - firstOrd(g.config, x.typ)
|
idx = idx - firstOrd(g.config, x.typ)
|
||||||
if idx >= 0 and idx < x.len: result = x.sons[int(idx)]
|
if idx >= 0 and idx < x.len: result = x.sons[int(idx)]
|
||||||
else: localError(g.config, n.info, "index out of bounds: " & $n)
|
else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len+1) & $n)
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
result = newNodeIT(nkCharLit, x.info, n.typ)
|
result = newNodeIT(nkCharLit, x.info, n.typ)
|
||||||
if idx >= 0 and idx < len(x.strVal):
|
if idx >= 0 and idx < len(x.strVal):
|
||||||
|
|
@ -501,7 +503,7 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
elif idx == len(x.strVal) and optLaxStrings in g.config.options:
|
elif idx == len(x.strVal) and optLaxStrings in g.config.options:
|
||||||
discard
|
discard
|
||||||
else:
|
else:
|
||||||
localError(g.config, n.info, "index out of bounds: " & $n)
|
localError(g.config, n.info, formatErrorIndexBound(idx, len(x.strVal)-1) & $n)
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
type
|
type
|
||||||
UncheckedCharArray = UncheckedArray[char]
|
UncheckedCharArray = UncheckedArray[char]
|
||||||
|
|
||||||
|
import system/helpers2
|
||||||
|
|
||||||
type
|
type
|
||||||
Buffer = ptr object
|
Buffer = ptr object
|
||||||
refcount: int
|
refcount: int
|
||||||
|
|
@ -49,11 +51,11 @@ proc len*(s: SharedString): int = s.len
|
||||||
|
|
||||||
proc `[]`*(s: SharedString; i: Natural): char =
|
proc `[]`*(s: SharedString; i: Natural): char =
|
||||||
if i < s.len: result = s.buffer.data[i+s.first]
|
if i < s.len: result = s.buffer.data[i+s.first]
|
||||||
else: raise newException(IndexError, "index out of bounds")
|
else: raise newException(IndexError, formatErrorIndexBound(i, s.len-1))
|
||||||
|
|
||||||
proc `[]=`*(s: var SharedString; i: Natural; value: char) =
|
proc `[]=`*(s: var SharedString; i: Natural; value: char) =
|
||||||
if i < s.len: s.buffer.data[i+s.first] = value
|
if i < s.len: s.buffer.data[i+s.first] = value
|
||||||
else: raise newException(IndexError, "index out of bounds")
|
else: raise newException(IndexError, formatErrorIndexBound(i, s.len-1))
|
||||||
|
|
||||||
proc `[]`*(s: SharedString; ab: HSlice[int, int]): SharedString =
|
proc `[]`*(s: SharedString; ab: HSlice[int, int]): SharedString =
|
||||||
#incRef(src.buffer)
|
#incRef(src.buffer)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
from strutils import parseInt, cmpIgnoreStyle, Digits
|
from strutils import parseInt, cmpIgnoreStyle, Digits
|
||||||
include "system/inclrtl"
|
include "system/inclrtl"
|
||||||
|
import system/helpers2
|
||||||
|
|
||||||
proc findNormalized(x: string, inArray: openarray[string]): int =
|
proc findNormalized(x: string, inArray: openarray[string]): int =
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
@ -85,7 +85,7 @@ proc getFormatArg(p: var FormatParser, a: openArray[string]): int =
|
||||||
result = parseInt(a[result])-1
|
result = parseInt(a[result])-1
|
||||||
else:
|
else:
|
||||||
raiseInvalidFormat("'#', '$', number or identifier expected")
|
raiseInvalidFormat("'#', '$', number or identifier expected")
|
||||||
if result >=% a.len: raiseInvalidFormat("index out of bounds: " & $result)
|
if result >=% a.len: raiseInvalidFormat(formatErrorIndexBound(result, a.len))
|
||||||
p.i = i
|
p.i = i
|
||||||
|
|
||||||
proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) {.
|
proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) {.
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
# Implementation of some runtime checks.
|
# Implementation of some runtime checks.
|
||||||
|
import system/helpers2
|
||||||
|
|
||||||
proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
|
proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
|
||||||
when hostOS == "standalone":
|
when hostOS == "standalone":
|
||||||
|
|
@ -15,6 +16,12 @@ proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
|
||||||
else:
|
else:
|
||||||
sysFatal(RangeError, "value out of range: ", $val)
|
sysFatal(RangeError, "value out of range: ", $val)
|
||||||
|
|
||||||
|
proc raiseIndexError3(i, a, b: int) {.compilerproc, noinline.} =
|
||||||
|
sysFatal(IndexError, formatErrorIndexBound(i, a, b))
|
||||||
|
|
||||||
|
proc raiseIndexError2(i, n: int) {.compilerproc, noinline.} =
|
||||||
|
sysFatal(IndexError, formatErrorIndexBound(i, n))
|
||||||
|
|
||||||
proc raiseIndexError() {.compilerproc, noinline.} =
|
proc raiseIndexError() {.compilerproc, noinline.} =
|
||||||
sysFatal(IndexError, "index out of bounds")
|
sysFatal(IndexError, "index out of bounds")
|
||||||
|
|
||||||
|
|
@ -25,7 +32,7 @@ proc chckIndx(i, a, b: int): int =
|
||||||
if i >= a and i <= b:
|
if i >= a and i <= b:
|
||||||
return i
|
return i
|
||||||
else:
|
else:
|
||||||
raiseIndexError()
|
raiseIndexError3(i, a, b)
|
||||||
|
|
||||||
proc chckRange(i, a, b: int): int =
|
proc chckRange(i, a, b: int): int =
|
||||||
if i >= a and i <= b:
|
if i >= a and i <= b:
|
||||||
|
|
|
||||||
5
lib/system/helpers2.nim
Normal file
5
lib/system/helpers2.nim
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
template formatErrorIndexBound*[T](i, a, b: T): string =
|
||||||
|
"index out of bounds: (a:" & $a & ") <= (i:" & $i & ") <= (b:" & $b & ") "
|
||||||
|
|
||||||
|
template formatErrorIndexBound*[T](i, n: T): string =
|
||||||
|
"index out of bounds: (i:" & $i & ") <= (n:" & $n & ") "
|
||||||
|
|
@ -1,14 +1,21 @@
|
||||||
discard """
|
discard """
|
||||||
errormsg: "index out of bounds"
|
errormsg: "index out of bounds: (a:0) <= (i:2) <= (b:1) "
|
||||||
line: 11
|
line: 18
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
block:
|
||||||
|
try:
|
||||||
|
let a = @[1,2]
|
||||||
|
echo a[3]
|
||||||
|
except Exception as e:
|
||||||
|
doAssert e.msg == "index out of bounds: (i:3) <= (n:1) "
|
||||||
|
|
||||||
type TTestArr = array[0..1, int16]
|
block:
|
||||||
var f: TTestArr
|
type TTestArr = array[0..1, int16]
|
||||||
f[0] = 30
|
var f: TTestArr
|
||||||
f[1] = 40
|
f[0] = 30
|
||||||
f[2] = 50
|
f[1] = 40
|
||||||
f[3] = 60
|
f[2] = 50
|
||||||
|
f[3] = 60
|
||||||
|
|
||||||
echo(repr(f))
|
echo(repr(f))
|
||||||
|
|
|
||||||
16
tests/misc/tinvalidarrayaccess2.nim
Normal file
16
tests/misc/tinvalidarrayaccess2.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "index out of bounds: (a:0) <= (i:3) <= (b:1) "
|
||||||
|
line: 9
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Note: merge in tinvalidarrayaccess.nim pending https://github.com/nim-lang/Nim/issues/9906
|
||||||
|
|
||||||
|
let a = [1,2]
|
||||||
|
echo a[3]
|
||||||
|
|
||||||
|
when false:
|
||||||
|
# TOOD: this case is not yet handled, giving: "index out of bounds"
|
||||||
|
proc fun()=
|
||||||
|
let a = @[1,2]
|
||||||
|
echo a[3]
|
||||||
|
static: fun()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue