mirror of
https://github.com/status-im/nim-ranges.git
synced 2025-02-21 08:58:19 +00:00
Fixed potential memory corruption, added allocStackArrayNoInit
This commit is contained in:
parent
e3f7793de5
commit
5dab1b35f4
@ -38,9 +38,9 @@
|
|||||||
##
|
##
|
||||||
|
|
||||||
type
|
type
|
||||||
StackArray*[T] = ptr object
|
StackArray*[T] = object
|
||||||
bufferLen: int32
|
bufferLen: int32
|
||||||
buffer: UncheckedArray[T]
|
buffer: ptr UncheckedArray[T]
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
proc alloca(n: int): pointer {.importc, header: "<malloc.h>".}
|
proc alloca(n: int): pointer {.importc, header: "<malloc.h>".}
|
||||||
@ -66,7 +66,7 @@ template `[]`*(a: StackArray, i: int): auto =
|
|||||||
if i < 0 or i >= a.len: raiseOutOfRange()
|
if i < 0 or i >= a.len: raiseOutOfRange()
|
||||||
a.buffer[i]
|
a.buffer[i]
|
||||||
|
|
||||||
proc `[]=`*(a: StackArray, i: int, val: a.T) =
|
proc `[]=`*(a: StackArray, i: int, val: a.T) {.inline.} =
|
||||||
if i < 0 or i >= a.len: raiseOutOfRange()
|
if i < 0 or i >= a.len: raiseOutOfRange()
|
||||||
a.buffer[i] = val
|
a.buffer[i] = val
|
||||||
|
|
||||||
@ -94,28 +94,34 @@ iterator mpairs*(a: var StackArray): (int, var a.T) =
|
|||||||
for i in 0 .. a.high:
|
for i in 0 .. a.high:
|
||||||
yield (i, a.buffer[i])
|
yield (i, a.buffer[i])
|
||||||
|
|
||||||
template allocStackArray*(T: typedesc, size: int): auto =
|
template allocaAux(sz: int, init: static[bool]): pointer =
|
||||||
|
let s = sz
|
||||||
|
let b = alloca(s)
|
||||||
|
when init: zeroMem(b, s)
|
||||||
|
b
|
||||||
|
|
||||||
|
template allocStackArrayAux(T: typedesc, size: int, init: static[bool]): StackArray[T] =
|
||||||
let sz = int(size) # Evaluate size only once
|
let sz = int(size) # Evaluate size only once
|
||||||
if sz < 0: raiseRangeError "allocation with a negative size"
|
if sz < 0: raiseRangeError "allocation with a negative size"
|
||||||
# XXX: is it possible to perform a stack size check before calling `alloca`?
|
# XXX: is it possible to perform a stack size check before calling `alloca`?
|
||||||
# On thread init, Nim may record the base address and the capacity of the stack,
|
# On thread init, Nim may record the base address and the capacity of the stack,
|
||||||
# so in theory we can verify that we still have enough room for the allocation.
|
# so in theory we can verify that we still have enough room for the allocation.
|
||||||
# Research this.
|
# Research this.
|
||||||
var
|
StackArray[T](bufferLen: int32(sz), buffer: cast[ptr UncheckedArray[T]](allocaAux(sz * sizeof(T), init)))
|
||||||
bufferSize = sz * sizeof(T)
|
|
||||||
totalSize = sizeof(int32) + bufferSize
|
template allocStackArray*(T: typedesc, size: int): StackArray[T] =
|
||||||
arr = cast[StackArray[T]](alloca(totalSize))
|
allocStackArrayAux(T, size, true)
|
||||||
zeroMem(addr arr.buffer[0], bufferSize)
|
|
||||||
arr.bufferLen = int32(sz)
|
template allocStackArrayNoInit*(T: typedesc, size: int): StackArray[T] =
|
||||||
arr
|
allocStackArrayAux(T, size, false)
|
||||||
|
|
||||||
template toOpenArray*(a: StackArray): auto =
|
template toOpenArray*(a: StackArray): auto =
|
||||||
toOpenArray(a.buffer, 0, a.high)
|
toOpenArray(a.buffer[], 0, a.high)
|
||||||
|
|
||||||
template toOpenArray*(a: StackArray, first: int): auto =
|
template toOpenArray*(a: StackArray, first: int): auto =
|
||||||
if first < 0 or first >= a.len: raiseOutOfRange()
|
if first < 0 or first >= a.len: raiseOutOfRange()
|
||||||
toOpenArray(a.buffer, first, a.high)
|
toOpenArray(a.buffer[], first, a.high)
|
||||||
|
|
||||||
template toOpenArray*(a: StackArray, first, last: int): auto =
|
template toOpenArray*(a: StackArray, first, last: int): auto =
|
||||||
if first < 0 or first >= last or last <= a.len: raiseOutOfRange()
|
if first < 0 or first >= last or last <= a.len: raiseOutOfRange()
|
||||||
toOpenArray(a.buffer, first, last)
|
toOpenArray(a.buffer[], first, last)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user