From d159a6efac61814d9bde27a1ca34f3e0dbe1b823 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 24 Mar 2019 14:08:11 +0000 Subject: [PATCH] cgtest: destroy the global PRNG after every cmdgen_main(). This prevents an assertion failure when random_ref() tries to create a new PRNG instance and finds there already is one. It also exposes bugs in which some code path forgot to initialise the PRNG when it was going to need it, such as the one fixed in the previous commit. --- cmdgen.c | 1 + putty.h | 7 +++++++ sshrand.c | 14 ++++++++++---- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/cmdgen.c b/cmdgen.c index 47795cfe..e1ff0ec8 100644 --- a/cmdgen.c +++ b/cmdgen.c @@ -1160,6 +1160,7 @@ void test(int retval, ...) printf("\n"); } ret = cmdgen_main(argc, argv); + random_clear(); if (ret != retval) { printf("FAILED retval (exp %d got %d):", retval, ret); diff --git a/putty.h b/putty.h index de4d410a..ee8952c2 100644 --- a/putty.h +++ b/putty.h @@ -1803,6 +1803,13 @@ extern int random_active; * calls random_ref on startup and random_unref on shutdown. */ void random_ref(void); void random_unref(void); +/* random_clear is equivalent to calling random_unref as many times as + * necessary to shut down the global PRNG instance completely. It's + * not needed in normal applications, but the command-line PuTTYgen + * test finds it useful to clean up after each invocation of the + * logical main() no matter whether it needed random numbers or + * not. */ +void random_clear(void); /* random_setup_special is used by PuTTYgen. It makes an extra-big * random number generator. */ void random_setup_special(); diff --git a/sshrand.c b/sshrand.c index 994c7cfc..b79fafc0 100644 --- a/sshrand.c +++ b/sshrand.c @@ -97,16 +97,22 @@ void random_reseed(ptrlen seed) prng_seed_finish(global_prng); } -void random_unref(void) +void random_clear(void) { - assert(random_active > 0); - if (random_active == 1) { + if (global_prng) { random_save_seed(); expire_timer_context(&random_timer_ctx); prng_free(global_prng); global_prng = NULL; + random_active = 0; } - random_active--; +} + +void random_unref(void) +{ + assert(random_active > 0); + if (--random_active == 0) + random_clear(); } void random_read(void *buf, size_t size)