winebuild: fix random generator like winegcc

Signed-off-by: Marko Semet <marko@marko10-000.de>
feature/deterministic
Marko Semet 2020-06-23 19:09:12 +02:00
parent 7f0b8eca21
commit d361a52e51
1 changed files with 117 additions and 38 deletions

View File

@ -1278,21 +1278,28 @@ const char *get_asm_string_section(void)
/* xorshift* random generator. Source: https://en.wikipedia.org/wiki/Xorshift#xorshift* */ /* xorshift* random generator. Source: https://en.wikipedia.org/wiki/Xorshift#xorshift* */
static uint64_t pseudorandom_state = 1; static uint64_t pseudorandom_state = 1;
extern char **environ; static const char* pseudorandom_source = NULL;
static size_t pseudorandom_source_size = 0;
uint64_t pseudorandom(uint64_t add_to_state) static uint64_t pseudorandom_algo(uint64_t* generator_state, uint64_t add_to_state)
{ {
uint64_t tmp = pseudorandom_state + add_to_state; uint64_t tmp = (*generator_state) + add_to_state;
tmp ^= tmp >> 12; tmp ^= tmp >> 12;
tmp ^= tmp << 25; tmp ^= tmp << 25;
tmp ^= tmp >> 27; tmp ^= tmp >> 27;
pseudorandom_state = tmp; (*generator_state) = tmp;
return tmp * UINT64_C(0x2545F4914F6CDD1D); return tmp * UINT64_C(0x2545F4914F6CDD1D);
} }
uint64_t pseudorandom(uint64_t add_to_state)
{
return pseudorandom_algo(&pseudorandom_state, add_to_state);
}
char pseudorandom_char(void) char pseudorandom_char(void)
{ {
char tmp = (char) (pseudorandom(0) % 62); char tmp;
tmp = (char) (pseudorandom(0) % 62);
if (tmp < 10) if (tmp < 10)
{ {
return '0' + tmp; return '0' + tmp;
@ -1309,18 +1316,26 @@ char pseudorandom_char(void)
int pseudorandom_tempfile(char* file) int pseudorandom_tempfile(char* file)
{ {
/* variables */
int result;
int counter;
char *filename_pos;
char *debug_filename;
FILE *debug_file;
/* replaces Xs */ /* replaces Xs */
for (char* tmp = file; (*tmp) != 0; tmp++) for (filename_pos = file; (*filename_pos) != 0; filename_pos++)
{ {
if ((*tmp) == 'X') if ((*filename_pos) == 'X')
{ {
(*tmp) = pseudorandom_char(); (*filename_pos) = pseudorandom_char();
} }
} }
/* try to open file */ /* try to open file */
int result; counter = 0;
int counter = 0;
do do
{ {
result = open(file, O_CREAT | O_EXCL | O_RDWR, 0600); result = open(file, O_CREAT | O_EXCL | O_RDWR, 0600);
@ -1331,52 +1346,116 @@ int pseudorandom_tempfile(char* file)
sleep(5); sleep(5);
counter++; counter++;
} while (counter <= 12); } while (counter <= 12);
/* add deebug info */
if ((result != -1) && (getenv("SOURCE_RANDOM_DEBUG") != NULL))
{
debug_filename = strmake("%s.random_debug", file);
debug_file = fopen(debug_filename, "wb");
fwrite(pseudorandom_source, 1, pseudorandom_source_size, debug_file);
fclose(debug_file);
free(debug_filename);
}
return result; return result;
} }
void init_random_generator(int argc, char **argv) void init_random_generator(int argc, char **argv)
{ {
/* variables */
uint64_t generator_state;
void *argv_data;
size_t argv_size;
unsigned int counter;
void *env_data;
size_t env_size;
char **tmp_envs;
char *buffer_pos;
char **env;
size_t length;
unsigned int i;
size_t j;
/* process environment */ /* process environment */
generator_state = 1;
env_size = 0;
{ {
/* copy environment variables and sort them */ /* sort environment variables */
char **tmp_envs; counter = 0;
unsigned int counter = 0; for (env = environ; (*env) != NULL; env++)
for (const char **env = environ; (*env) != 0; env++, counter++) {}
tmp_envs = (char**) malloc(sizeof(char*) * counter);
for (unsigned int i = 0; i < counter; i++)
{ {
size_t length = strlen(environ[i]) + 1; counter++;
char* tmp = malloc(length); env_size += strlen(*env) + 1;
memcpy(tmp, environ[i], length); }
tmp_envs[i] = tmp; tmp_envs = (char**) malloc(sizeof(char*) * counter);
for (i = 0; i < counter; i++)
{
tmp_envs[i] = (char*) (environ[i]);
} }
qsort(tmp_envs, counter, sizeof(char*), (int(*)(const void*, const void*)) &strcmp); qsort(tmp_envs, counter, sizeof(char*), (int(*)(const void*, const void*)) &strcmp);
/* add sorted environment to random generator */ /* and copy them */
for (unsigned int i = 0; i < counter; i++) env_data = malloc(env_size * sizeof(char));
buffer_pos = env_data;
for (i = 0; i < counter; i++)
{ {
size_t j_max = strlen(tmp_envs[i]); length = strlen(tmp_envs[i]) + 1;
for (size_t j = 0; j < j_max; j++) memcpy(buffer_pos, tmp_envs[i], length);
{ buffer_pos += length;
pseudorandom(tmp_envs[i][j]); }
}
/* add sorted environment to random generator */
for (j = 0; j < env_size; j++)
{
pseudorandom_algo(&generator_state, ((unsigned char*) env_data)[j]);
} }
/* free temp environment */ /* free temp environment */
for (unsigned int i = 0; i < counter; i++)
{
free(tmp_envs[i]);
}
free(tmp_envs); free(tmp_envs);
} }
/* process argv */ /* copy argv */
for (int i = 0; i < argc; i++) argv_size = 0;
for (i = 0; i < argc; i++)
{ {
size_t j_max = strlen(argv[i]); argv_size += strlen(argv[i]) + 1;
for (size_t j = 0; j < j_max; j++)
{
pseudorandom(argv[i][j]);
}
} }
argv_data = malloc(sizeof(char) * argv_size);
buffer_pos = argv_data;
for (i = 0; i < argc; i++)
{
length = strlen(argv[i]) + 1;
memcpy(buffer_pos, argv[i], length);
buffer_pos += length;
}
/* add arguments to gnerator */
for (j = 0; j < argv_size; j++)
{
pseudorandom_algo(&generator_state, ((unsigned char*) argv_data)[j]);
}
/* add debug if required */
if (getenv("SOURCE_RANDOM_DEBUG") != NULL)
{
/* gen field */
pseudorandom_source_size = env_size + argv_size + sizeof(generator_state);
buffer_pos = malloc(sizeof(char) * pseudorandom_source_size);
pseudorandom_source = buffer_pos;
/* copy data into it */
memcpy(buffer_pos, env_data, env_size);
buffer_pos += env_size;
memcpy(buffer_pos, argv_data, argv_size);
buffer_pos += argv_size;
memcpy(buffer_pos, &generator_state, sizeof(generator_state));
}
/* set state and free rest */
free(env_data);
free(argv_data);
pseudorandom_state = generator_state;
} }