rand/rand.c (rand_getgood): Stretch the output buffer if necessary.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 23 Dec 2023 14:13:34 +0000 (14:13 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 23 Dec 2023 14:30:41 +0000 (14:30 +0000)
commit6c83f206dee6c7c646bf50105b41de858b5242d6
treeca58e3bca2408d461aa02ce63ad6210036075620
parentce7001d8ef72928ff966e3c9da1c62ce1d00d2c0
rand/rand.c (rand_getgood): Stretch the output buffer if necessary.

It's possible to have `r->o == RAND_BUFSZ' in the main loop, while
`r->obits' is larger than the requested size.  The following program
contrives this situation, though it can (and does) happen organically.

#include <stdio.h>
#include <stdlib.h>

#include "noise.h"
#include "rand.h"

int main(void)
{
  rand_pool pool;
  unsigned char buf[64];
  size_t n;

  rand_init(&pool);
  rand_noisesrc(&pool, &noise_source);
  rand_seed(&pool, 64);

  while (pool.obits < RAND_OBITS) rand_seed(&pool, RAND_IBITS);
  while (pool.o < RAND_BUFSZ) {
    n = RAND_BUFSZ - pool.o; if (n > sizeof(buf)) n = sizeof(buf);
    rand_getgood(&pool, buf, n);
  }
  rand_getgood(&pool, buf, 4);
  return (0);
}

When this happens, `rand_getgood' gets stuck in an infinite loop,
trimming the chunk size to zero because the output buffer is exhausted,
but not refilling it because there's still notional entropy remaining.
Detect this situation and stretch the output buffer when there's nothing
left, as in `rand_get'.
rand/rand.c