delorie.com/djgpp/bugs/show.cgi   search  
Bug 000171

When Created: 08/04/1997 10:39:57
Against DJGPP version: 2.01
By whom: bukinm@inp.nsk.su
Abstract: putenv bug (aka Emacs crashes with certain number of vars in DOS environment)
  Emacs crashes when certain number of variables is defined in DOS environment.
Maybe, this number depends on the number of variables that come from DJGPP.ENV.

  One reason for this is a bug in putenv. When adding new variable
in array (that is `char** environ') and array is full, space for
terminating (char*)0 element is not allocated.

Offending code (djlsr201.zip:src/libc/compat/stdlib/putenv.c):
/*
 * ecount holds index of terminating (char*)0 in environ.
 * emax holds index of last element in environ, for which space is allocated.
 */
...
if (ecount >= emax)
{
  ...
  emax += 10;
  new_environ = malloc (emax * sizeof (char*));
  ...
/*
 * Now, emax holds index of element outside of space allocated for environ.
 * and after some putenvs ecount can have the same value as emax.
 * This means that terminating (char*)0 can be overwritten (in rare cases when
 * terminating (char*)0 gets outside of actual memory allocated by malloc).
 */

E.g. when total DOS number of vars is 21 and DJGPP.ENV number of vars is 10,
total is 31, emax and ecount both are equal to 31, block allocated by malloc
is nearest power of 2 -- (4 + 31 * 4) = 128, and index 31 points outside
of this block, and value stored by this index can be overwritten by heap
handling routines.

P.S. this bug affects almost any djgpp program which does not replace
__crt0_load_environment_file or does use putenv calls.

Solution added: 08/04/1997 10:44:45
By whom: bukinm@inp.nsk.su
  Allocate space for terminating (char*)0 element.
Emacs was rebuilt with the patch below and tested in environment
where original crashed. Either offending number of variables is
different now, or this problem was solved.

*** src/libc/compat/stdlib/putenv.c.~1~ Sun Oct  6 00:27:44 1996
--- src/libc/compat/stdlib/putenv.c     Mon Aug  4 20:40:32 1997
***************
*** 106,112 ****
    {
      char **enew;
      emax += 10;
!     enew = (char **)malloc(emax * sizeof(char *));
      if (enew == 0)
        return -1;
      memcpy(enew, environ, ecount * sizeof(char *));
--- 106,112 ----
    {
      char **enew;
      emax += 10;
!     enew = (char **)malloc((emax + 1) * sizeof(char *));
      if (enew == 0)
        return -1;
      memcpy(enew, environ, ecount * sizeof(char *));

Fixed in version on 04/12/1999 11:00:45
By whom: eliz@is.elta.co.il



  webmaster     delorie software   privacy  
  Copyright © 2010   by DJ Delorie     Updated Jul 2010