Skip to content

Commit

Permalink
fixes #20865; fixes #20987; Missing bounds check in array slicing (#2…
Browse files Browse the repository at this point in the history
…3814)

fixes #20865
fixes #20987

(cherry picked from commit e53a2ed)
  • Loading branch information
ringabout authored and narimiran committed Sep 13, 2024
1 parent 7d0cdfc commit f09b612
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 11 deletions.
12 changes: 6 additions & 6 deletions compiler/ccgcalls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
line(p, cpsStmts, pl)
if canRaise: raiseExit(p)

proc genBoundsCheck(p: BProc; arr, a, b: TLoc)
proc genBoundsCheck(p: BProc; arr, a, b: TLoc; arrTyp: PType)

proc reifiedOpenArray(n: PNode): bool {.inline.} =
var x = n
Expand All @@ -172,15 +172,15 @@ proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType; prepareF
initLocExpr(p, q[1], a)
initLocExpr(p, q[2], b)
initLocExpr(p, q[3], c)
# bug #23321: In the function mapType, ptrs (tyPtr, tyVar, tyLent, tyRef)
# are mapped into ctPtrToArray, the dereference of which is skipped
# in the `genDeref`. We need to skip these ptrs here
let ty = skipTypes(a.t, abstractVar+{tyPtr, tyRef})
# but first produce the required index checks:
if optBoundsCheck in p.options:
genBoundsCheck(p, a, b, c)
genBoundsCheck(p, a, b, c, ty)
if prepareForMutation:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
# bug #23321: In the function mapType, ptrs (tyPtr, tyVar, tyLent, tyRef)
# are mapped into ctPtrToArray, the dereference of which is skipped
# in the `genref`. We need to skip these ptrs here
let ty = skipTypes(a.t, abstractVar+{tyPtr, tyRef})
let dest = getTypeDesc(p.module, destType)
let lengthExpr = "($1)-($2)+1" % [rdLoc(c), rdLoc(b)]
case ty.kind
Expand Down
6 changes: 3 additions & 3 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1039,8 +1039,8 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) =
putIntoDest(p, d, n,
ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)

proc genBoundsCheck(p: BProc; arr, a, b: TLoc) =
let ty = skipTypes(arr.t, abstractVarRange)
proc genBoundsCheck(p: BProc; arr, a, b: TLoc; arrTyp: PType) =
let ty = arrTyp
case ty.kind
of tyOpenArray, tyVarargs:
if reifiedOpenArray(arr.lode):
Expand Down Expand Up @@ -1889,7 +1889,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
initLocExpr(p, a[2], b)
initLocExpr(p, a[3], c)
if optBoundsCheck in p.options:
genBoundsCheck(p, m, b, c)
genBoundsCheck(p, m, b, c, skipTypes(m.t, abstractVarRange))
if op == mHigh:
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1))", [rdLoc(b), rdLoc(c)]))
else:
Expand Down
16 changes: 16 additions & 0 deletions tests/arc/topenarray.nim
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,19 @@ block:
doAssert foo(noBugConst) == expected
let noBugSeq = @["0", "c", "a"]
doAssert foo(noBugSeq) == expected

block: # bug #20865
var p: pointer
var x: array[0, int]
# echo toOpenArray(x, 0, 1)[0] # Raises IndexDefect
doAssertRaises(IndexDefect):
echo toOpenArray(cast[ptr array[0, int]](p)[], 0, 1)[0] # Does not raise IndexDefect

block: # bug #20987
var v: array[1, byte]

var p = cast[ptr array[0, byte]](addr v)

doAssertRaises(IndexDefect):
echo toOpenArray(p[], 1, 2)

4 changes: 2 additions & 2 deletions tests/overload/t8829.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ block:
let txt = "Hello World"

template `[]`[T](p: ptr T, span: Slice[int]): untyped =
toOpenArray(cast[ptr array[0, T]](p)[], span.a, span.b)
toOpenArray(cast[ptr UncheckedArray[T]](p), span.a, span.b)

doAssert $cast[ptr uint8](txt[0].addr)[0 ..< txt.len] ==
"[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]"
Expand All @@ -12,7 +12,7 @@ block:
let txt = "Hello World"

template `[]`[T](p: ptr T, span: Slice[int]): untyped =
toOpenArray(cast[ptr array[0, T]](p)[], span.a, span.b)
toOpenArray(cast[ptr UncheckedArray[T]](p), span.a, span.b)

doAssert $cast[ptr uint8](txt[0].addr)[0 ..< txt.len] ==
"[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]"

0 comments on commit f09b612

Please sign in to comment.