Am 05.01.2014 13:00 schrieb "Martin Storsjö" <[email protected]>: > > On Fri, 3 Jan 2014, Martin Storsjö wrote: > >> From: Michael Niedermayer <[email protected]> >> >> The new code is faster and reuses the previous state in case of >> multiple calls. >> >> The previous code could easily end up in near-infinite loops, >> if the difference between two clock() calls never was larger than >> 1. >> >> This makes fate-parseutils finish in finite time when run in wine, >> if CryptGenRandom isn't available (which e.g. isn't available if >> targeting Windows RT/metro). >> --- >> This is a revived patch, earlier discussion at >> http://patches.libav.org/patch/28570/ and >> http://patches.libav.org/patch/28568/. >> >> Using a dynamically allocated SHA context now (with some sort of >> fallback for the case if allocation fails), avoiding reading outside >> of the buffer, and not allocating a too large digest buffer. >> --- >> libavutil/random_seed.c | 51 ++++++++++++++++++++++++++++------------------- >> 1 file changed, 30 insertions(+), 21 deletions(-) >> >> diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c >> index 4680081..26884cb 100644 >> --- a/libavutil/random_seed.c >> +++ b/libavutil/random_seed.c >> @@ -31,8 +31,11 @@ >> #include <math.h> >> #include <time.h> >> #include "internal.h" >> +#include "intreadwrite.h" >> +#include "mem.h" >> #include "timer.h" >> #include "random_seed.h" >> +#include "sha.h" >> >> static int read_random(uint32_t *dst, const char *file) >> { >> @@ -53,34 +56,40 @@ static int read_random(uint32_t *dst, const char *file) >> >> static uint32_t get_generic_seed(void) >> { >> + struct AVSHA *sha = av_sha_alloc(); >> clock_t last_t = 0; >> - int bits = 0; >> - uint64_t random = 0; >> - unsigned i; >> - float s = 0.000000000001; >> + static uint64_t i = 0; >> + static uint32_t buffer[512] = { 0 }; >> + unsigned char digest[20]; >> + uint64_t last_i = i; >> >> - for (i = 0; bits < 64; i++) { >> + for (;;) { >> clock_t t = clock(); >> - if (last_t && fabs(t - last_t) > s || t == (clock_t) -1) { >> - if (i < 10000 && s < (1 << 24)) { >> - s += s; >> - i = t = 0; >> - } else { >> - random = 2 * random + (i & 1); >> - bits++; >> - } >> + >> + if (last_t == t) { >> + buffer[i & 511]++; >> + } else { >> + buffer[++i & 511] += (t - last_t) % 3294638521U; >> + if (last_i && i - last_i > 4 || i - last_i > 64) >> + break; >> } >> last_t = t; >> } >> -#ifdef AV_READ_TIME >> - random ^= AV_READ_TIME(); >> -#else >> - random ^= clock(); >> -#endif >> >> - random += random >> 32; >> - >> - return random; >> + if (!sha) { >> + uint32_t seed = 0; >> + int j; >> + // Unable to allocate an sha context, just xor the buffer together >> + // to create something hopefully unique. >> + for (j = 0; j < 512; j++) >> + seed ^= buffer[j]; >> + return seed; > > > So I guess the seeds produced in this case won't be all that strong - is that acceptable for the odd case that we run out of memory here? > > We've deprecated av_sha_size and the struct itself is opaque so we can't easily place it on the stack (and even if we'd use av_sha_size, we'd have to get the struct aligned properly). OTOH since both of these are within lavu we could expose the actual struct definition here, but that's not good practice either... >
Is worrying about an out of memory condition really worth it? It could return an error for all we should care, if it actually still produces numbers even better. - Hendrik _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
