mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-12 14:48:14 +00:00
@@ -28,6 +28,10 @@ proc toLit*[T](a: T): PNode =
|
||||
elif T is tuple:
|
||||
result = newTree(nkTupleConstr)
|
||||
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:
|
||||
result = newTree(nkObjConstr)
|
||||
result.add(newNode(nkEmpty))
|
||||
|
||||
@@ -56,3 +56,10 @@ proc getNode*(a: VmArgs; i: Natural): PNode =
|
||||
doAssert i < a.rc-1
|
||||
doAssert a.slots[i+a.rb+1].kind == rkNode
|
||||
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:
|
||||
#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,
|
||||
floor, ceil, `mod`
|
||||
|
||||
when declared(math.copySign):
|
||||
from math import copySign
|
||||
from std/math import copySign
|
||||
|
||||
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 times import cpuTime
|
||||
|
||||
from hashes import hash
|
||||
from osproc import nil
|
||||
|
||||
# There are some useful procs in vmconv.
|
||||
import vmconv
|
||||
|
||||
template mathop(op) {.dirty.} =
|
||||
@@ -304,3 +308,35 @@ proc registerAdditionalOps*(c: PCtx) =
|
||||
let fn = getNode(a, 0)
|
||||
setResult(a, (fn.typ != nil and tfNoSideEffect in fn.typ.flags) or
|
||||
(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)
|
||||
|
||||
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>
|
||||
#include <sys/syscall.h>"""
|
||||
|
||||
@@ -209,7 +210,7 @@ elif defined(freebsd):
|
||||
# errno is set to indicate the error.
|
||||
|
||||
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):
|
||||
{.passL: "-framework Security".}
|
||||
@@ -284,7 +285,7 @@ proc urandomInternalImpl(dest: var openArray[byte]): int {.inline.} =
|
||||
|
||||
proc urandom*(dest: var openArray[byte]): bool =
|
||||
## 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,
|
||||
## without calling underlying operating system api.
|
||||
@@ -305,4 +306,4 @@ proc urandom*(size: Natural): seq[byte] {.inline.} =
|
||||
when defined(js): discard urandomInternalImpl(result)
|
||||
else:
|
||||
if not urandom(result):
|
||||
raiseOsError(osLastError())
|
||||
raiseOSError(osLastError())
|
||||
|
||||
@@ -1,13 +1,36 @@
|
||||
discard """
|
||||
targets: "c cpp js"
|
||||
matrix: "--experimental:vmopsDanger"
|
||||
"""
|
||||
|
||||
import std/sysrand
|
||||
|
||||
|
||||
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
|
||||
template main() =
|
||||
block:
|
||||
var x = array[5, byte].default
|
||||
doAssert urandom(x)
|
||||
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user