mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-29 08:11:08 +00:00
Update.
* stdlib/random_r.c (__random_r): Rewrite last patch to fix buffer overwriting bugs.
This commit is contained in:
parent
195d0dd4aa
commit
6958e78dd1
@ -1,5 +1,8 @@
|
|||||||
1998-05-22 Ulrich Drepper <drepper@cygnus.com>
|
1998-05-22 Ulrich Drepper <drepper@cygnus.com>
|
||||||
|
|
||||||
|
* stdlib/random_r.c (__random_r): Rewrite last patch to fix buffer
|
||||||
|
overwriting bugs.
|
||||||
|
|
||||||
* libio/strops.c (_IO_str_underflow): Read newly available
|
* libio/strops.c (_IO_str_underflow): Read newly available
|
||||||
character from buffer as unsigned.
|
character from buffer as unsigned.
|
||||||
|
|
||||||
|
@ -107,17 +107,18 @@
|
|||||||
|
|
||||||
struct random_poly_info
|
struct random_poly_info
|
||||||
{
|
{
|
||||||
char seps[MAX_TYPES - 1];
|
int seps[MAX_TYPES];
|
||||||
char degrees[MAX_TYPES - 1];
|
int degrees[MAX_TYPES];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct random_poly_info random_poly_info =
|
static const struct random_poly_info random_poly_info =
|
||||||
{
|
{
|
||||||
{ SEP_1, SEP_2, SEP_3, SEP_4 },
|
{ SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 },
|
||||||
{ DEG_1, DEG_2, DEG_3, DEG_4 },
|
{ DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialize the random number generator based on the given seed. If the
|
/* Initialize the random number generator based on the given seed. If the
|
||||||
type is the trivial no-state-information type, just remember the seed.
|
type is the trivial no-state-information type, just remember the seed.
|
||||||
@ -134,68 +135,55 @@ __srandom_r (seed, buf)
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
int32_t *state;
|
int32_t *state;
|
||||||
|
long int i;
|
||||||
|
long int word;
|
||||||
|
int32_t *dst;
|
||||||
|
int kc;
|
||||||
|
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
type = buf->rand_type;
|
type = buf->rand_type;
|
||||||
if ((unsigned)type >= MAX_TYPES)
|
if ((unsigned int) type >= MAX_TYPES)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */
|
|
||||||
state = buf->state;
|
state = buf->state;
|
||||||
|
/* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */
|
||||||
if (seed == 0)
|
if (seed == 0)
|
||||||
seed = 1;
|
seed = 1;
|
||||||
state[0] = seed;
|
state[0] = seed;
|
||||||
if (type == TYPE_0)
|
if (type == TYPE_0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
dst = state;
|
||||||
|
word = seed;
|
||||||
|
kc = buf->rand_deg;
|
||||||
|
for (i = 1; i < kc; ++i)
|
||||||
{
|
{
|
||||||
int degree;
|
/* This does:
|
||||||
long int word;
|
state[i] = (16807 * state[i - 1]) % 2147483647;
|
||||||
int jc;
|
but avoids overflowing 31 bits. */
|
||||||
int32_t *dst;
|
long int hi = word / 127773;
|
||||||
int kc;
|
long int lo = word % 127773;
|
||||||
int separation;
|
word = 16807 * lo - 2836 * hi;
|
||||||
|
if (word < 0)
|
||||||
degree = buf->rand_deg;
|
word += 2147483647;
|
||||||
jc = degree - 1;
|
*++dst = word;
|
||||||
dst = state;
|
|
||||||
word = seed;
|
|
||||||
while (--jc >= 0)
|
|
||||||
{
|
|
||||||
long int hi;
|
|
||||||
long int lo;
|
|
||||||
|
|
||||||
/* This does:
|
|
||||||
state[i] = (16807 * state[i - 1]) % 2147483647;
|
|
||||||
but avoids overflowing 31 bits. */
|
|
||||||
++dst;
|
|
||||||
hi = word / 127773;
|
|
||||||
lo = word % 127773;
|
|
||||||
word = 16807 * lo - 2836 * hi;
|
|
||||||
if (word < 0)
|
|
||||||
word += 2147483647;
|
|
||||||
*dst = word;
|
|
||||||
}
|
|
||||||
state = buf->state;
|
|
||||||
degree = buf->rand_deg;
|
|
||||||
separation = buf->rand_sep;
|
|
||||||
buf->fptr = &state[separation];
|
|
||||||
buf->rptr = &state[0];
|
|
||||||
kc = 10 * degree;
|
|
||||||
while (--kc >= 0)
|
|
||||||
{
|
|
||||||
int32_t discard;
|
|
||||||
(void) __random_r (buf, &discard);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
|
|
||||||
fail:
|
buf->fptr = &state[buf->rand_sep];
|
||||||
return -1;
|
buf->rptr = &state[0];
|
||||||
|
kc *= 10;
|
||||||
|
while (--kc >= 0)
|
||||||
|
{
|
||||||
|
int32_t discard;
|
||||||
|
(void) __random_r (buf, &discard);
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
weak_alias (__srandom_r, srandom_r)
|
weak_alias (__srandom_r, srandom_r)
|
||||||
@ -222,8 +210,6 @@ __initstate_r (seed, arg_state, n, buf)
|
|||||||
int degree;
|
int degree;
|
||||||
int separation;
|
int separation;
|
||||||
int32_t *state;
|
int32_t *state;
|
||||||
int mess;
|
|
||||||
const struct random_poly_info *rpi;
|
|
||||||
|
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -233,35 +219,33 @@ __initstate_r (seed, arg_state, n, buf)
|
|||||||
else if (n < BREAK_1)
|
else if (n < BREAK_1)
|
||||||
{
|
{
|
||||||
if (n < BREAK_0)
|
if (n < BREAK_0)
|
||||||
goto fail;
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
type = TYPE_0;
|
type = TYPE_0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
type = n < BREAK_2 ? TYPE_1 : TYPE_2;
|
type = n < BREAK_2 ? TYPE_1 : TYPE_2;
|
||||||
|
|
||||||
|
degree = random_poly_info.degrees[type];
|
||||||
|
separation = random_poly_info.seps[type];
|
||||||
|
|
||||||
|
buf->rand_type = type;
|
||||||
|
buf->rand_sep = separation;
|
||||||
|
buf->rand_deg = degree;
|
||||||
state = &((int32_t *) arg_state)[1]; /* First location. */
|
state = &((int32_t *) arg_state)[1]; /* First location. */
|
||||||
buf->state = state;
|
|
||||||
mess = TYPE_0;
|
|
||||||
if (type == TYPE_0)
|
|
||||||
goto skip_to_here;
|
|
||||||
|
|
||||||
rpi = &random_poly_info;
|
|
||||||
degree = rpi->degrees[type - 1];
|
|
||||||
separation = rpi->seps[type - 1];
|
|
||||||
|
|
||||||
/* Must set END_PTR before srandom. */
|
/* Must set END_PTR before srandom. */
|
||||||
buf->end_ptr = &state[degree];
|
buf->end_ptr = &state[degree];
|
||||||
|
|
||||||
buf->rand_deg = degree;
|
buf->state = state;
|
||||||
buf->rand_sep = separation;
|
|
||||||
|
|
||||||
mess = (buf->rptr - state) * MAX_TYPES + type;
|
|
||||||
|
|
||||||
skip_to_here:
|
|
||||||
state[-1] = mess;
|
|
||||||
|
|
||||||
__srandom_r (seed, buf);
|
__srandom_r (seed, buf);
|
||||||
|
|
||||||
|
state[-1] = TYPE_0;
|
||||||
|
if (type != TYPE_0)
|
||||||
|
state[-1] = (buf->rptr - state) * MAX_TYPES + type;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -283,59 +267,41 @@ __setstate_r (arg_state, buf)
|
|||||||
void *arg_state;
|
void *arg_state;
|
||||||
struct random_data *buf;
|
struct random_data *buf;
|
||||||
{
|
{
|
||||||
int32_t *new_state;
|
int32_t *new_state = (int32_t *) arg_state;
|
||||||
int type;
|
int type = new_state[0] % MAX_TYPES;
|
||||||
int rear;
|
int old_type;
|
||||||
int32_t *old_state;
|
int32_t *old_state;
|
||||||
int32_t *ns1;
|
|
||||||
int degree;
|
int degree;
|
||||||
int separation;
|
int separation;
|
||||||
int mess;
|
|
||||||
int old_type;
|
|
||||||
int new_mess;
|
|
||||||
int *old_rptr;
|
|
||||||
const struct random_poly_info *rpi;
|
|
||||||
|
|
||||||
if (buf == NULL)
|
if (buf == NULL || type < TYPE_0 || type >= TYPE_4)
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
old_type = buf->rand_type;
|
old_type = buf->rand_type;
|
||||||
old_state = buf->state;
|
old_state = buf->state;
|
||||||
old_rptr = buf->rptr;
|
if (old_type == TYPE_0)
|
||||||
mess = old_type;
|
old_state[-1] = TYPE_0;
|
||||||
if (old_type != TYPE_0)
|
else
|
||||||
mess += (old_rptr - old_state) * MAX_TYPES;
|
old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type;
|
||||||
old_state[-1] = mess;
|
|
||||||
|
|
||||||
new_state = (int32_t *) arg_state;
|
buf->rand_deg = degree = random_poly_info.degrees[type];
|
||||||
new_mess = new_state[0];
|
buf->rand_sep = separation = random_poly_info.seps[type];
|
||||||
type = new_mess % MAX_TYPES;
|
buf->rand_type = type;
|
||||||
rear = new_mess / MAX_TYPES;
|
|
||||||
|
|
||||||
rpi = &random_poly_info;
|
|
||||||
degree = rpi->degrees[type - 1];
|
|
||||||
separation = rpi->seps[type - 1];
|
|
||||||
if (rear >= degree)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
ns1 = &new_state[1];
|
|
||||||
if (type != TYPE_0)
|
if (type != TYPE_0)
|
||||||
{
|
{
|
||||||
int t;
|
int rear = new_state[0] / MAX_TYPES;
|
||||||
|
buf->rptr = &new_state[rear];
|
||||||
t = rear + separation;
|
buf->fptr = &new_state[(rear + separation) % degree];
|
||||||
if (t >= degree)
|
|
||||||
t -= degree;
|
|
||||||
buf->rptr = &ns1[rear];
|
|
||||||
buf->fptr = &ns1[t];
|
|
||||||
buf->rand_deg = degree;
|
|
||||||
buf->rand_sep = separation;
|
|
||||||
buf->end_ptr = &ns1[degree];
|
|
||||||
}
|
}
|
||||||
|
buf->state = &new_state[1];
|
||||||
|
/* Set end_ptr too. */
|
||||||
|
buf->end_ptr = &new_state[degree];
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
__set_errno (EINVAL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,85 +314,58 @@ weak_alias (__setstate_r, setstate_r)
|
|||||||
the one at the front pointer. Then both pointers are advanced to the next
|
the one at the front pointer. Then both pointers are advanced to the next
|
||||||
location cyclically in the table. The value returned is the sum generated,
|
location cyclically in the table. The value returned is the sum generated,
|
||||||
reduced to 31 bits by throwing away the "least random" low bit.
|
reduced to 31 bits by throwing away the "least random" low bit.
|
||||||
Returns a 31-bit random number. */
|
Note: The code takes advantage of the fact that both the front and
|
||||||
|
rear pointers can't wrap on the same call by not testing the rear
|
||||||
|
pointer if the front one has wrapped. Returns a 31-bit random number. */
|
||||||
|
|
||||||
int
|
int
|
||||||
__random_r (buf, result)
|
__random_r (buf, result)
|
||||||
struct random_data *buf;
|
struct random_data *buf;
|
||||||
int32_t *result;
|
int32_t *result;
|
||||||
{
|
{
|
||||||
int32_t *res_ptr;
|
int32_t *state;
|
||||||
int rand_type;
|
|
||||||
|
|
||||||
res_ptr = result;
|
if (buf == NULL || result == NULL)
|
||||||
rand_type = buf->rand_type;
|
|
||||||
if (buf == NULL || res_ptr == NULL)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (rand_type == TYPE_0)
|
state = buf->state;
|
||||||
goto old_style;
|
|
||||||
|
|
||||||
{
|
if (buf->rand_type == TYPE_0)
|
||||||
int32_t *fp0;
|
{
|
||||||
int32_t *rp0;
|
int32_t val = state[0];
|
||||||
int32_t sum;
|
val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
|
||||||
int32_t fval;
|
state[0] = val;
|
||||||
int32_t rval;
|
*result = val;
|
||||||
int32_t rez;
|
}
|
||||||
int32_t *fp1;
|
else
|
||||||
int32_t *rp1;
|
{
|
||||||
int32_t *end;
|
int32_t *fptr = buf->fptr;
|
||||||
int32_t *begin;
|
int32_t *rptr = buf->rptr;
|
||||||
|
int32_t *end_ptr = buf->end_ptr;
|
||||||
|
int32_t val;
|
||||||
|
|
||||||
/* 0 */
|
val = *fptr += *rptr;
|
||||||
fp0 = buf->fptr;
|
/* Chucking least random bit. */
|
||||||
rp0 = buf->rptr;
|
*result = (val >> 1) & 0x7fffffff;
|
||||||
|
++fptr;
|
||||||
/* 1 */
|
if (fptr >= end_ptr)
|
||||||
fval = *fp0;
|
{
|
||||||
rval = *rp0;
|
fptr = state;
|
||||||
fp1 = fp0 + 1;
|
++rptr;
|
||||||
|
}
|
||||||
/* 2 */
|
else
|
||||||
sum = fval + rval;
|
{
|
||||||
rp1 = rp0 + 1;
|
++rptr;
|
||||||
|
if (rptr >= end_ptr)
|
||||||
/* 3 */
|
rptr = state;
|
||||||
rez = (sum >> 1) & 0x7FFFFFFF;
|
}
|
||||||
*fp0 = sum;
|
buf->fptr = fptr;
|
||||||
end = buf->end_ptr;
|
buf->rptr = rptr;
|
||||||
|
}
|
||||||
/* 4 */
|
return 0;
|
||||||
*res_ptr = rez;
|
|
||||||
begin = buf->state;
|
|
||||||
if (fp1 == end)
|
|
||||||
fp1 = begin;
|
|
||||||
if (rp1 == end)
|
|
||||||
rp1 = begin;
|
|
||||||
|
|
||||||
/* 5 */
|
|
||||||
buf->fptr = fp1;
|
|
||||||
buf->rptr = rp1;
|
|
||||||
}
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
old_style:
|
|
||||||
{
|
|
||||||
int32_t *state;
|
|
||||||
int32_t rez;
|
|
||||||
|
|
||||||
state = buf->state;
|
|
||||||
rez = ((*state * 1103515245) + 12345) & 0x7FFFFFFF;
|
|
||||||
*res_ptr = rez;
|
|
||||||
*state = rez;
|
|
||||||
}
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
done:
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
weak_alias (__random_r, random_r)
|
weak_alias (__random_r, random_r)
|
||||||
|
Loading…
Reference in New Issue
Block a user