improve how random seed state is determined

Added "STATIC bool blum_initialized = false" to zrandom.c to improve
how the code detects if the Blum-Blum-Shub pseudo-random number
generator is seeded or not, and how to free the state correctly.

NOTE: There is a very minor memory leak in zrandom.c that will be
fixed in a later release.
This commit is contained in:
Landon Curt Noll
2023-12-08 13:51:14 -08:00
parent c724227ef9
commit fbaff69c92
2 changed files with 63 additions and 22 deletions

View File

@@ -1,4 +1,5 @@
The following are the changes from calc version 2.15.0.2 to date: The following are the changes from calc version 2.15.0.2 to date:
Updated BUGS about MSYS2 on Windows compiling of calc. Updated BUGS about MSYS2 on Windows compiling of calc.
Added more git related checks and sanity checks to chk_tree. Added more git related checks and sanity checks to chk_tree.
@@ -21,6 +22,13 @@ The following are the changes from calc version 2.15.0.2 to date:
Fixed the check for <sys/mount.h> when forming have_sys_mount.h. Fixed the check for <sys/mount.h> when forming have_sys_mount.h.
Thanks goes to GitHub user @gromit1811 for their pull request. Thanks goes to GitHub user @gromit1811 for their pull request.
Added "STATIC bool blum_initialized = false" to zrandom.c to improve
how the code detects if the Blum-Blum-Shub pseudo-random number
generator is seeded or not, and how to free the state correctly.
NOTE: There is a very minor memory leak in zrandom.c that will be
fixed in a later release.
The following are the changes from calc version 2.14.3.5 to 2.15.0.1: The following are the changes from calc version 2.14.3.5 to 2.15.0.1:

View File

@@ -1107,6 +1107,7 @@
* current Blum generator state * current Blum generator state
*/ */
STATIC RANDOM blum; STATIC RANDOM blum;
STATIC bool blum_initialized = false; /* true ==> blum has a seeded and initialized state */
/* /*
@@ -2272,11 +2273,14 @@ zsrandom1(CONST ZVALUE seed, bool need_ret)
/* /*
* initialize state if first call * initialize state if first call
*/ */
if (!blum.seeded) { if (blum_initialized == false || !blum.seeded) {
p_blum = randomcopy(&init_blum); p_blum = randomcopy(&init_blum);
randomfree(&blum); if (blum_initialized == true) {
randomfree(&blum);
}
blum = *p_blum; blum = *p_blum;
free(p_blum); free(p_blum);
blum_initialized = true;
} }
/* /*
@@ -2342,6 +2346,9 @@ zsrandom1(CONST ZVALUE seed, bool need_ret)
* reserved seed * reserved seed
*/ */
} else { } else {
if (ret != NULL) {
randomfree(ret);
}
math_error("srandom seed must be 0 or >= 2^32"); math_error("srandom seed must be 0 or >= 2^32");
not_reached(); not_reached();
} }
@@ -2384,11 +2391,14 @@ zsrandom2(CONST ZVALUE seed, CONST ZVALUE newn)
/* /*
* initialize state if first call * initialize state if first call
*/ */
if (!blum.seeded) { if (blum_initialized == false || !blum.seeded) {
p_blum = randomcopy(&init_blum); p_blum = randomcopy(&init_blum);
randomfree(&blum); if (blum_initialized == true) {
randomfree(&blum);
}
blum = *p_blum; blum = *p_blum;
free(p_blum); free(p_blum);
blum_initialized = true;
} }
/* /*
@@ -2409,11 +2419,13 @@ zsrandom2(CONST ZVALUE seed, CONST ZVALUE newn)
* preset moduli only if small newn * preset moduli only if small newn
*/ */
if (ziszero(newn)) { if (ziszero(newn)) {
randomfree(ret);
math_error("srandom newn == 0 reserved for future use"); math_error("srandom newn == 0 reserved for future use");
not_reached(); not_reached();
} }
set = (HALF)z1tol(newn); set = (HALF)z1tol(newn);
if (!zistiny(newn) || set > BLUM_PREGEN) { if (!zistiny(newn) || set > BLUM_PREGEN) {
randomfree(ret);
math_error("srandom small newn must be [1,20]"); math_error("srandom small newn must be [1,20]");
not_reached(); not_reached();
} }
@@ -2433,7 +2445,7 @@ zsrandom2(CONST ZVALUE seed, CONST ZVALUE newn)
* Otherwise non-zero seeds are processed as 1 arg calls * Otherwise non-zero seeds are processed as 1 arg calls
*/ */
} else { } else {
zsrandom1(seed, false); (void) zsrandom1(seed, false);
} }
/* /*
@@ -2452,6 +2464,7 @@ zsrandom2(CONST ZVALUE seed, CONST ZVALUE newn)
* Blum modulus must be 1 mod 4 * Blum modulus must be 1 mod 4
*/ */
if (newn.v[0] % 4 != 1) { if (newn.v[0] % 4 != 1) {
randomfree(ret);
math_error("srandom large newn must be 1 mod 4"); math_error("srandom large newn must be 1 mod 4");
not_reached(); not_reached();
} }
@@ -2498,6 +2511,7 @@ zsrandom2(CONST ZVALUE seed, CONST ZVALUE newn)
* reserved newn * reserved newn
*/ */
} else { } else {
randomfree(ret);
math_error("srandom newn must be [1,20] or >= 2^32"); math_error("srandom newn must be [1,20] or >= 2^32");
not_reached(); not_reached();
} }
@@ -2543,11 +2557,14 @@ zsrandom4(CONST ZVALUE seed, CONST ZVALUE ip, CONST ZVALUE iq, long trials)
/* /*
* initialize state if first call * initialize state if first call
*/ */
if (!blum.seeded) { if (blum_initialized == false || !blum.seeded) {
p_blum = randomcopy(&init_blum); p_blum = randomcopy(&init_blum);
randomfree(&blum); if (blum_initialized == true) {
randomfree(&blum);
}
blum = *p_blum; blum = *p_blum;
free(p_blum); free(p_blum);
blum_initialized = true;
} }
/* /*
@@ -2559,10 +2576,12 @@ zsrandom4(CONST ZVALUE seed, CONST ZVALUE ip, CONST ZVALUE iq, long trials)
* search the 'p' and 'q' Blum prime (3 mod 4) candidates * search the 'p' and 'q' Blum prime (3 mod 4) candidates
*/ */
if (!znextcand(ip, trials, _zero_, _three_, _four_, &p)) { if (!znextcand(ip, trials, _zero_, _three_, _four_, &p)) {
randomfree(ret);
math_error("failed to find 1st Blum prime"); math_error("failed to find 1st Blum prime");
not_reached(); not_reached();
} }
if (!znextcand(iq, trials, _zero_, _three_, _four_, &q)) { if (!znextcand(iq, trials, _zero_, _three_, _four_, &q)) {
randomfree(ret);
math_error("failed to find 2nd Blum prime"); math_error("failed to find 2nd Blum prime");
not_reached(); not_reached();
} }
@@ -2640,11 +2659,14 @@ zsetrandom(CONST RANDOM *state)
/* /*
* initialize state if first call * initialize state if first call
*/ */
if (!blum.seeded) { if (blum_initialized == false || !blum.seeded) {
p_blum = randomcopy(&init_blum); p_blum = randomcopy(&init_blum);
randomfree(&blum); if (blum_initialized == true) {
randomfree(&blum);
}
blum = *p_blum; blum = *p_blum;
free(p_blum); free(p_blum);
blum_initialized = true;
} }
/* /*
@@ -2684,11 +2706,14 @@ zrandomskip(long cnt)
/* /*
* initialize state if first call * initialize state if first call
*/ */
if (!blum.seeded) { if (blum_initialized == false || !blum.seeded) {
p_blum = randomcopy(&init_blum); p_blum = randomcopy(&init_blum);
randomfree(&blum); if (blum_initialized == true) {
randomfree(&blum);
}
blum = *p_blum; blum = *p_blum;
free(p_blum); free(p_blum);
blum_initialized = true;
} }
loglogn = (long)blum.loglogn; loglogn = (long)blum.loglogn;
new_r.len = 0; /* paranoia */ new_r.len = 0; /* paranoia */
@@ -2798,11 +2823,14 @@ zrandom(long cnt, ZVALUE *res)
/* /*
* initialize state if first call * initialize state if first call
*/ */
if (!blum.seeded) { if (blum_initialized == false || !blum.seeded) {
p_blum = randomcopy(&init_blum); p_blum = randomcopy(&init_blum);
randomfree(&blum); if (blum_initialized == true) {
randomfree(&blum);
}
blum = *p_blum; blum = *p_blum;
free(p_blum); free(p_blum);
blum_initialized = true;
} }
loglogn = blum.loglogn; loglogn = blum.loglogn;
mask = blum.mask; mask = blum.mask;
@@ -3120,16 +3148,18 @@ randomfree(RANDOM *state)
not_reached(); not_reached();
} }
/* free the values */ /* clear the seed */
state->seeded = 0;
state->bits = 0; /* paranoia */
state->loglogn = 0; /* paranoia */
state->buffer = 0; /* paranoia */
state->mask = 0; /* paranoia */
/* free the values - unless they are one of the default states */
zfree_random(state->n); zfree_random(state->n);
zfree_random(state->r); zfree_random(state->r);
/* free it if it is not pre-defined */ /* free the RANDOM structure if it is NOT our static blum value */
state->seeded = 0;
state->bits = 0; /* paranoia */
state->buffer = 0;
/* free it if it is not pre-defined */
if (state != &blum) { if (state != &blum) {
free(state); free(state);
} }
@@ -3223,8 +3253,10 @@ randomprint(CONST RANDOM *UNUSED(state), int UNUSED(flags))
void void
random_libcalc_cleanup(void) random_libcalc_cleanup(void)
{ {
/* free our state - let zfree_random protect the default state */ /* free our state if seed was initialized - zfree_random protect default states */
randomfree(&blum); if (blum_initialized == true && blum.seeded) {
randomfree(&blum);
}
return; return;
} }
@@ -3238,6 +3270,7 @@ random_libcalc_cleanup(void)
S_FUNC void S_FUNC void
zfree_random(ZVALUE z) zfree_random(ZVALUE z)
{ {
/* do not free if NULL or one of the default states */
if (z.v != NULL && if (z.v != NULL &&
z.v != h_ndefvec && z.v != h_rdefvec && z.v != h_rdefvec_2 && z.v != h_ndefvec && z.v != h_rdefvec && z.v != h_rdefvec_2 &&
z.v != h_nvec01 && z.v != h_rvec01 && z.v != h_nvec01 && z.v != h_rvec01 &&