Skip to content

Commit 6fc083d

Browse files
committed
Make unpredictableSeed use getrandom (syscall) on Linux
1 parent 1b24204 commit 6fc083d

File tree

1 file changed

+56
-2
lines changed

1 file changed

+56
-2
lines changed

std/random.d

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,24 @@ else
17721772
}
17731773
}
17741774

1775+
version (linux)
1776+
{
1777+
// `getrandom()` was introduced in Linux 3.17.
1778+
1779+
// Shim for missing bindings in druntime
1780+
version (none)
1781+
import core.sys.linux.sys.random : getrandom;
1782+
else
1783+
{
1784+
import core.sys.posix.sys.types;
1785+
extern extern(C) ssize_t getrandom(
1786+
void* buf,
1787+
size_t buflen,
1788+
uint flags,
1789+
) @system nothrow @nogc;
1790+
}
1791+
}
1792+
17751793
/**
17761794
A "good" seed for initializing random number engines. Initializing
17771795
with $(D_PARAM unpredictableSeed) makes engines generate different
@@ -1788,7 +1806,25 @@ how excellent the source of entropy is.
17881806
*/
17891807
@property uint unpredictableSeed() @trusted nothrow @nogc
17901808
{
1791-
version (AnyARC4Random)
1809+
version (linux)
1810+
{
1811+
uint buffer;
1812+
1813+
/*
1814+
getrandom(2):
1815+
If the _urandom_ source has been initialized, reads of up to
1816+
256 bytes will always return as many bytes as requested and
1817+
will not be interrupted by signals. No such guarantees apply
1818+
for larger buffer sizes.
1819+
*/
1820+
static assert(buffer.sizeof <= 256);
1821+
1822+
const status = (() @trusted => getrandom(&buffer, buffer.sizeof, 0))();
1823+
assert(status == buffer.sizeof);
1824+
1825+
return buffer;
1826+
}
1827+
else version (AnyARC4Random)
17921828
{
17931829
return arc4random();
17941830
}
@@ -1837,7 +1873,25 @@ if (isUnsigned!UIntType)
18371873
/// ditto
18381874
@property UIntType unpredictableSeed() @nogc nothrow @trusted
18391875
{
1840-
version (AnyARC4Random)
1876+
version (linux)
1877+
{
1878+
UIntType buffer;
1879+
1880+
/*
1881+
getrandom(2):
1882+
If the _urandom_ source has been initialized, reads of up to
1883+
256 bytes will always return as many bytes as requested and
1884+
will not be interrupted by signals. No such guarantees apply
1885+
for larger buffer sizes.
1886+
*/
1887+
static assert(buffer.sizeof <= 256);
1888+
1889+
const status = (() @trusted => getrandom(&buffer, buffer.sizeof, 0))();
1890+
assert(status == buffer.sizeof);
1891+
1892+
return buffer;
1893+
}
1894+
else version (AnyARC4Random)
18411895
{
18421896
static if (UIntType.sizeof <= uint.sizeof)
18431897
{

0 commit comments

Comments
 (0)