/* malloc1.c (emx+gcc) */

#include <stdio.h>
#include <stdlib.h>

static void *xrealloc (void *p, size_t n)
{
  if (_heapchk () > 1) abort ();
  p = realloc (p, n);
  if (_heapchk () > 1) abort ();
  if (p == NULL) abort ();
  printf ("%p\n", (void *)p);
  return p;
}


int main (void)
{
  void *p1, *p2, *p3, *p4;

  p1 = xrealloc (NULL, 65500);
  free (p1);

  /* 0x30004    p1      65500 free
     0x3ffe4    -          32 free */

  p1 = xrealloc (NULL, 20000);
  p2 = xrealloc (NULL, 10000);
  p3 = xrealloc (NULL, 35500);

  /* 0x30004    p1      20000 used
     0x34e28    p2      10000 used
     0x3753c    -       35492 free
     0x3ffe4    -          32 free */

  free (p2);
  p2 = xrealloc (NULL, 4900);
  p4 = xrealloc (NULL, 4900);
  free (p2);
  free (p4);

  /* Here we have the following situation:

     0x30004    p1      20000 used
     0x34e28    p2       4900 free
     0x36150    p4       4900 free   <--- _malloc_rover+4
     0x37478    -         192 free
     0x3753c    p3      35500 used
     0x3ffec    -          24 free

     The first pass of _malloc2() called by the following realloc()
     call collapses adjacent free blocks and forgets to move
     _malloc_rover from 0x36150-4 to 0x34e28-4.  Then, realloc()
     expands the heap without changing _malloc_rover.  In consequence,
     _malloc_rover will no longer point to an element of the chain and
     a `successful' allocation at _malloc_rover will corrupt the heap
     (this heap corruption is not shown by this program as we'll abort
     due to _heapchk() detecting the _malloc_rover problem after the
     realloc() call). */

  p3 = xrealloc (p3, 60000);
  return 0;
}
