parent
f32ffb6ed8
commit
4f118721be
5 changed files with 90 additions and 19 deletions
|
|
@ -28,6 +28,10 @@ proc toLit*[T](a: T): PNode =
|
||||||
elif T is tuple:
|
elif T is tuple:
|
||||||
result = newTree(nkTupleConstr)
|
result = newTree(nkTupleConstr)
|
||||||
for ai in fields(a): result.add toLit(ai)
|
for ai in fields(a): result.add toLit(ai)
|
||||||
|
elif T is seq:
|
||||||
|
result = newNode(nkBracket)
|
||||||
|
for ai in a:
|
||||||
|
result.add toLit(ai)
|
||||||
elif T is object:
|
elif T is object:
|
||||||
result = newTree(nkObjConstr)
|
result = newTree(nkObjConstr)
|
||||||
result.add(newNode(nkEmpty))
|
result.add(newNode(nkEmpty))
|
||||||
|
|
|
||||||
|
|
@ -56,3 +56,10 @@ proc getNode*(a: VmArgs; i: Natural): PNode =
|
||||||
doAssert i < a.rc-1
|
doAssert i < a.rc-1
|
||||||
doAssert a.slots[i+a.rb+1].kind == rkNode
|
doAssert a.slots[i+a.rb+1].kind == rkNode
|
||||||
result = a.slots[i+a.rb+1].node
|
result = a.slots[i+a.rb+1].node
|
||||||
|
|
||||||
|
proc getNodeAddr*(a: VmArgs; i: Natural): PNode =
|
||||||
|
doAssert i < a.rc-1
|
||||||
|
doAssert a.slots[i+a.rb+1].kind == rkNodeAddr
|
||||||
|
let nodeAddr = a.slots[i+a.rb+1].nodeAddr
|
||||||
|
doAssert nodeAddr != nil
|
||||||
|
result = nodeAddr[]
|
||||||
|
|
|
||||||
|
|
@ -9,24 +9,28 @@
|
||||||
|
|
||||||
# Unfortunately this cannot be a module yet:
|
# Unfortunately this cannot be a module yet:
|
||||||
#import vmdeps, vm
|
#import vmdeps, vm
|
||||||
from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
|
from std/math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
|
||||||
arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc,
|
arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc,
|
||||||
floor, ceil, `mod`
|
floor, ceil, `mod`
|
||||||
|
|
||||||
when declared(math.copySign):
|
when declared(math.copySign):
|
||||||
from math import copySign
|
from std/math import copySign
|
||||||
|
|
||||||
when declared(math.signbit):
|
when declared(math.signbit):
|
||||||
from math import signbit
|
from std/math import signbit
|
||||||
|
|
||||||
|
from std/os import getEnv, existsEnv, dirExists, fileExists, putEnv, walkDir,
|
||||||
|
getAppFilename, raiseOSError, osLastError
|
||||||
|
|
||||||
|
from std/md5 import getMD5
|
||||||
|
from std/times import cpuTime
|
||||||
|
from std/hashes import hash
|
||||||
|
from std/osproc import nil
|
||||||
|
from std/sysrand import urandom
|
||||||
|
|
||||||
from os import getEnv, existsEnv, dirExists, fileExists, putEnv, walkDir, getAppFilename
|
|
||||||
from md5 import getMD5
|
|
||||||
from sighashes import symBodyDigest
|
from sighashes import symBodyDigest
|
||||||
from times import cpuTime
|
|
||||||
|
|
||||||
from hashes import hash
|
|
||||||
from osproc import nil
|
|
||||||
|
|
||||||
|
# There are some useful procs in vmconv.
|
||||||
import vmconv
|
import vmconv
|
||||||
|
|
||||||
template mathop(op) {.dirty.} =
|
template mathop(op) {.dirty.} =
|
||||||
|
|
@ -304,3 +308,35 @@ proc registerAdditionalOps*(c: PCtx) =
|
||||||
let fn = getNode(a, 0)
|
let fn = getNode(a, 0)
|
||||||
setResult(a, (fn.typ != nil and tfNoSideEffect in fn.typ.flags) or
|
setResult(a, (fn.typ != nil and tfNoSideEffect in fn.typ.flags) or
|
||||||
(fn.kind == nkSym and fn.sym.kind == skFunc))
|
(fn.kind == nkSym and fn.sym.kind == skFunc))
|
||||||
|
|
||||||
|
if vmopsDanger in c.config.features:
|
||||||
|
proc urandomImpl(a: VmArgs) =
|
||||||
|
doAssert a.numArgs == 1
|
||||||
|
let kind = a.slots[a.rb+1].kind
|
||||||
|
case kind
|
||||||
|
of rkInt:
|
||||||
|
setResult(a, urandom(a.getInt(0)).toLit)
|
||||||
|
of rkNode, rkNodeAddr:
|
||||||
|
let n =
|
||||||
|
if kind == rkNode:
|
||||||
|
a.getNode(0)
|
||||||
|
else:
|
||||||
|
a.getNodeAddr(0)
|
||||||
|
|
||||||
|
let length = n.len
|
||||||
|
|
||||||
|
## TODO refactor using vmconv.fromLit
|
||||||
|
var res = newSeq[uint8](length)
|
||||||
|
for i in 0 ..< length:
|
||||||
|
res[i] = byte(n[i].intVal)
|
||||||
|
|
||||||
|
let isSuccess = urandom(res)
|
||||||
|
|
||||||
|
for i in 0 ..< length:
|
||||||
|
n[i].intVal = BiggestInt(res[i])
|
||||||
|
|
||||||
|
setResult(a, isSuccess)
|
||||||
|
else:
|
||||||
|
doAssert false, $kind
|
||||||
|
|
||||||
|
registerCallback c, "stdlib.sysrand.urandom", urandomImpl
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,8 @@ elif defined(windows):
|
||||||
result = randomBytes(addr dest[0], size)
|
result = randomBytes(addr dest[0], size)
|
||||||
|
|
||||||
elif defined(linux):
|
elif defined(linux):
|
||||||
let SYS_getrandom {.importc: "SYS_getrandom", header: "<sys/syscall.h>".}: clong
|
# TODO using let, pending bootstrap >= 1.4.0
|
||||||
|
var SYS_getrandom {.importc: "SYS_getrandom", header: "<sys/syscall.h>".}: clong
|
||||||
const syscallHeader = """#include <unistd.h>
|
const syscallHeader = """#include <unistd.h>
|
||||||
#include <sys/syscall.h>"""
|
#include <sys/syscall.h>"""
|
||||||
|
|
||||||
|
|
@ -209,7 +210,7 @@ elif defined(freebsd):
|
||||||
# errno is set to indicate the error.
|
# errno is set to indicate the error.
|
||||||
|
|
||||||
proc getRandomImpl(p: pointer, size: int): int {.inline.} =
|
proc getRandomImpl(p: pointer, size: int): int {.inline.} =
|
||||||
result = getrandom(p, csize_t(batchSize), 0)
|
result = getrandom(p, csize_t(size), 0)
|
||||||
|
|
||||||
elif defined(ios):
|
elif defined(ios):
|
||||||
{.passL: "-framework Security".}
|
{.passL: "-framework Security".}
|
||||||
|
|
@ -284,7 +285,7 @@ proc urandomInternalImpl(dest: var openArray[byte]): int {.inline.} =
|
||||||
|
|
||||||
proc urandom*(dest: var openArray[byte]): bool =
|
proc urandom*(dest: var openArray[byte]): bool =
|
||||||
## Fills `dest` with random bytes suitable for cryptographic use.
|
## Fills `dest` with random bytes suitable for cryptographic use.
|
||||||
## If succeed, returns `true`.
|
## If the call succeeds, returns `true`.
|
||||||
##
|
##
|
||||||
## If `dest` is empty, `urandom` immediately returns success,
|
## If `dest` is empty, `urandom` immediately returns success,
|
||||||
## without calling underlying operating system api.
|
## without calling underlying operating system api.
|
||||||
|
|
@ -305,4 +306,4 @@ proc urandom*(size: Natural): seq[byte] {.inline.} =
|
||||||
when defined(js): discard urandomInternalImpl(result)
|
when defined(js): discard urandomInternalImpl(result)
|
||||||
else:
|
else:
|
||||||
if not urandom(result):
|
if not urandom(result):
|
||||||
raiseOsError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,36 @@
|
||||||
discard """
|
discard """
|
||||||
targets: "c cpp js"
|
targets: "c cpp js"
|
||||||
|
matrix: "--experimental:vmopsDanger"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import std/sysrand
|
import std/sysrand
|
||||||
|
|
||||||
|
|
||||||
doAssert urandom(0).len == 0
|
template main() =
|
||||||
doAssert urandom(10).len == 10
|
block:
|
||||||
doAssert urandom(20).len == 20
|
var x = array[5, byte].default
|
||||||
doAssert urandom(120).len == 120
|
doAssert urandom(x)
|
||||||
doAssert urandom(113).len == 113
|
|
||||||
doAssert urandom(1234) != urandom(1234) # unlikely to fail in practice
|
block:
|
||||||
|
var x = newSeq[byte](5)
|
||||||
|
doAssert urandom(x)
|
||||||
|
|
||||||
|
block:
|
||||||
|
var x = @[byte(0), 0, 0, 0, 0]
|
||||||
|
doAssert urandom(x)
|
||||||
|
|
||||||
|
block:
|
||||||
|
var x = @[byte(1), 2, 3, 4, 5]
|
||||||
|
doAssert urandom(x)
|
||||||
|
|
||||||
|
block:
|
||||||
|
doAssert urandom(0).len == 0
|
||||||
|
doAssert urandom(10).len == 10
|
||||||
|
doAssert urandom(20).len == 20
|
||||||
|
doAssert urandom(120).len == 120
|
||||||
|
doAssert urandom(113).len == 113
|
||||||
|
doAssert urandom(1234) != urandom(1234) # unlikely to fail in practice
|
||||||
|
|
||||||
|
|
||||||
|
static: main()
|
||||||
|
main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue