Summary
In the Linux implementation of randomBytes (nimcrypto/sysrand.nim), the retry loop for partial getrandom(2) reads computes the resume pointer p but then passes the original buffer start pbytes to the syscall:
if srng.getRandomPresent:
var res = 0
while res < nbytes:
p = cast[pointer](cast[uint](pbytes) + uint(res))
let bytesRead = syscall(SYS_getrandom, pbytes, nbytes - res, 0) # <-- should be `p`
if bytesRead > 0:
res += bytesRead
When getrandom returns a partial read, the next iteration overwrites the beginning of the buffer instead of continuing where the previous read stopped. Meanwhile res keeps accumulating until it reaches nbytes, so the function returns full success.
Impact
If the first read returns k < nbytes bytes, the loop's subsequent reads fill [0, nbytes - k) again, and the region [max(k, nbytes - k), nbytes) is never written at all. The caller receives a return value indicating the whole buffer was filled with random data, while its tail still contains whatever was in memory before the call (uninitialized stack/heap contents).
For a CSPRNG API this is a silent failure: keys, nonces, or salts generated through this path can contain predictable bytes.
Summary
In the Linux implementation of
randomBytes(nimcrypto/sysrand.nim), the retry loop for partial getrandom(2) reads computes the resume pointerpbut then passes the original buffer startpbytesto the syscall:When
getrandomreturns a partial read, the next iteration overwrites the beginning of the buffer instead of continuing where the previous read stopped. Meanwhilereskeeps accumulating until it reachesnbytes, so the function returns full success.Impact
If the first read returns k < nbytes bytes, the loop's subsequent reads fill [0, nbytes - k) again, and the region [max(k, nbytes - k), nbytes) is never written at all. The caller receives a return value indicating the whole buffer was filled with random data, while its tail still contains whatever was in memory before the call (uninitialized stack/heap contents).
For a CSPRNG API this is a silent failure: keys, nonces, or salts generated through this path can contain predictable bytes.