Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refs #9880 show index and bound in lots of index out of bounds errors #9881

Merged
merged 1 commit into from
Dec 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -867,15 +867,15 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
# semantic pass has already checked for const index expressions
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)):
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)))
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)))
else:
let idx = getOrdValue(y)
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)
putIntoDest(p, d, n,
ropecg(p.module, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage)
Expand Down Expand Up @@ -915,7 +915,7 @@ proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
initLocExpr(p, x, a)
initLocExpr(p, y, b) # emit range check:
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 ``>``!
inheritLocation(d, a)
putIntoDest(p, d, n,
Expand All @@ -931,11 +931,11 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
if optBoundsCheck in p.options:
if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options):
linefmt(p, cpsStmts,
"if ((NU)($1) > (NU)$2) #raiseIndexError();$n",
"if ((NU)($1) > (NU)$2) #raiseIndexError2($1,$2);$n",
rdLoc(b), lenExpr(p, a))
else:
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))
if d.k == locNone: d.storage = OnHeap
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
Expand Down
2 changes: 2 additions & 0 deletions compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
lowerings, tables, sets, ndi, lineinfos, pathutils, transf

import system/helpers2

when not defined(leanCompiler):
import semparallel

Expand Down
8 changes: 5 additions & 3 deletions compiler/semfold.nim
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import
nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
commands, magicsys, modulegraphs, strtabs, lineinfos

import system/helpers2

proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
case skipTypes(n.typ, abstractVarRange).kind
of tyInt:
Expand Down Expand Up @@ -489,19 +491,19 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
result = x.sons[int(idx)]
if result.kind == nkExprColonExpr: result = result.sons[1]
else:
localError(g.config, n.info, "index out of bounds: " & $n)
localError(g.config, n.info, formatErrorIndexBound(idx, sonsLen(x)+1) & $n)
of nkBracket:
idx = idx - firstOrd(g.config, x.typ)
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:
result = newNodeIT(nkCharLit, x.info, n.typ)
if idx >= 0 and idx < len(x.strVal):
result.intVal = ord(x.strVal[int(idx)])
elif idx == len(x.strVal) and optLaxStrings in g.config.options:
discard
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

proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
Expand Down
6 changes: 4 additions & 2 deletions lib/pure/collections/sharedstrings.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
type
UncheckedCharArray = UncheckedArray[char]

import system/helpers2

type
Buffer = ptr object
refcount: int
Expand Down Expand Up @@ -49,11 +51,11 @@ proc len*(s: SharedString): int = s.len

proc `[]`*(s: SharedString; i: Natural): char =
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) =
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 =
#incRef(src.buffer)
Expand Down
4 changes: 2 additions & 2 deletions lib/pure/subexes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

from strutils import parseInt, cmpIgnoreStyle, Digits
include "system/inclrtl"

import system/helpers2

proc findNormalized(x: string, inArray: openarray[string]): int =
var i = 0
Expand Down Expand Up @@ -85,7 +85,7 @@ proc getFormatArg(p: var FormatParser, a: openArray[string]): int =
result = parseInt(a[result])-1
else:
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

proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) {.
Expand Down
9 changes: 8 additions & 1 deletion lib/system/chcks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@
#

# Implementation of some runtime checks.
import system/helpers2

proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
when hostOS == "standalone":
sysFatal(RangeError, "value out of range")
else:
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.} =
sysFatal(IndexError, "index out of bounds")

Expand All @@ -25,7 +32,7 @@ proc chckIndx(i, a, b: int): int =
if i >= a and i <= b:
return i
else:
raiseIndexError()
raiseIndexError3(i, a, b)

proc chckRange(i, a, b: int): int =
if i >= a and i <= b:
Expand Down
5 changes: 5 additions & 0 deletions lib/system/helpers2.nim
Original file line number Diff line number Diff line change
@@ -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 & ") "
25 changes: 16 additions & 9 deletions tests/misc/tinvalidarrayaccess.nim
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
discard """
errormsg: "index out of bounds"
line: 11
errormsg: "index out of bounds: (a:0) <= (i:2) <= (b:1) "
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]
var f: TTestArr
f[0] = 30
f[1] = 40
f[2] = 50
f[3] = 60
block:
type TTestArr = array[0..1, int16]
var f: TTestArr
f[0] = 30
f[1] = 40
f[2] = 50
f[3] = 60

echo(repr(f))
echo(repr(f))
16 changes: 16 additions & 0 deletions tests/misc/tinvalidarrayaccess2.nim
Original file line number Diff line number Diff line change
@@ -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()