This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Multiple bugs in stdlib function setstate()


>Submitter-Id:	net
>Originator:	Michael Fischer
>Organization:
  ==================================================
  | Michael Fischer <fischer-michael@cs.yale.edu>  |
  | Professor of Computer Science                  |
  ==================================================
>
>Confidential:	no
>Synopsis:	Multiple bugs in __setstate_r() [stdlib/random_r.c]
>Severity:	critical
>Priority:	medium
>Category:	libc
>Class:		sw-bug
>Release:	libc-2.1.3
>Environment:
Host type: i386-redhat-linux-gnu
System: Linux daphne.home 2.2.16 #14 Sun Jun 18 23:14:21 EDT 2000 i686 unknown
Architecture: i686

Addons: c_stubs crypt glibc-compat linuxthreads
Build CFLAGS: -g -O3
Build CC: egcs
Compiler version: egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
Kernel headers: 2.2.16
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: yes
Build omitfp: no
Build bounded: no
Build static-nss: no
Stdio: libio

>Description:
1.  setstate(newstate) fails (returns NULL) when newstate is size 256 
    (TYPE_4 generator).

2.  setstate(newstate) corrupts new state, causing subsequent
    setstate(newstate) call to fail (returns NULL).

3.  setstate(NULL) causes segmentation fault.

>How-To-Repeat:
1.  
/* Expose setstate() bug with size 256 generator */

#include <stdlib.h>

int main()
{
  char* newstate[256];
  char* oldstate;
  unsigned int seed = 12344321;
  int i;

  oldstate = initstate(seed, newstate, 256);
  if (setstate(newstate) == NULL) printf("setstate returns NULL\n");
  return 0;
}

2.
/* Expose setstate() bug with state corruption */

#include <stdlib.h>

int main()
{
  char* newstate[128];
  unsigned int seed = 12344321;

  initstate(seed, newstate, 128);
  setstate(newstate);
  if (setstate(newstate) == NULL) printf("setstate returns NULL\n");
  return 0;
}

3.
/* Expose NULL argument bug to setstate */

#include <stdlib.h>

int main()
{
  setstate(NULL);		/* causes segmentation fault */
  return 0;
}


>Fix:
1.  In stdlib/random_r.c:  Change line 288 from
  if (type < TYPE_0 || type >= TYPE_4)
to
  if (type < TYPE_0 || type > TYPE_4)

2.  In stdlib/random_r.c:  Change lines 298-299 from
      buf->rptr = &new_state[rear];
      buf->fptr = &new_state[(rear + separation) % degree];
to
      buf->rptr = &new_state[1 + rear];
      buf->fptr = &new_state[1 + (rear + separation) % degree];

Discussion: The problem is the +1 offset between buf->state and
new_state.  buf->rptr and buf->fptr should end up pointing to
buf->state[rear] and buf->state[(rear + separation) % degree].
However, &buf->state[0] = &new_state[1], so &buf->state[k] =
&new_state[1 + k]; hence the need to add 1 to the two subscripts
above.  (Other fixes are of course also possible.)

3.  In stdlib/random_r.c:  Change line 277 from
  if (buf == NULL)
to
  if (buf == NULL || arg_state == NULL)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]