Re: putenv broken in the current CVS

Giorgio Dal Molin <[email protected]> Sat, 17 Aug 2019 11:47:50 +0200
Newsgroups gmane.linux.lib.dietlibc
Message-ID <[email protected]>
On 8/16/19 11:07 AM, [email protected] wrote:
> 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
> 
Hi,

after a bit of code review I think this could be the right for loop
to fix putenv():

int putenv(const char *string) {
...
  for (i=envc=0, ep[i]; ep[i]; ++i) {
    if (*string == ep[i][0] &&
	!memcmp(string,ep[i],len) &&
	ep[i][len]=='=') {
      if (remove) continue;
      ep[envc++]=string;
      remove=1;		// remove dupes
    } else
      ep[envc++]=ep[i];
  }
...

giorgio