putenv broken in the current CVS

[email protected] Fri, 16 Aug 2019 11:07:53 +0200 (CEST)
Newsgroups gmane.linux.lib.dietlibc
Message-ID <[email protected]>
Hi,

I think the current implementation of putenv() in lib/putenv.c is broken.

Here is the code:

int putenv(const char *string) {
  size_t len;
  size_t i, envc;
  int remove=0;
  char *tmp;
  const char **ep;
  char **newenv;
  static char **origenv;
  if (!origenv) origenv=environ;
  if (!(tmp=strchr(string,'='))) {
    len=strlen(string);
    remove=1;
  } else
    len=tmp-string;
  ep=(const char**)environ;
  if (!ep) return 0;
  for (i=envc=0, ep[i]; ep[i]; ++i) {
    if (*string == ep[i][0] &&
	!memcmp(string,*ep,len) &&
	(*ep)[len]=='=') {
      if (remove) continue;
      ep[envc++]=string;
      remove=1;		// remove dupes
    }
  }
  if (!remove) {
    // we were trying to replace something and didn't find it
    // so realloc and add here
    newenv = (char**) realloc(environ==origenv?0:environ,
			      (envc+2)*sizeof(char*));
    if (!newenv) return -1;
    if (envc && (environ==origenv)) {
      memcpy(newenv,origenv,envc*sizeof(char*));
    }
    newenv[envc++]=(char*)string;
    environ=newenv;
  }
  environ[envc]=0;		// terminate env
  return 0;
}

In the for loop you use both ep[i] and *ep, I think it's wrong because ep
is never incremented and always points to the beginning of the environ array.
Even with this problem fixed the implementation remains broken.

I found this problem because the fgetty doesn't work anymore with the current dietlibc:
/bin/login2 segfaults because it gets a NULL from getenv("TTY") even if /sbin/fgetty just
set it to "/dev/tty6".

giorgio