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

Reply via email to