bostic@okeeffe.berkeley.EDU.UUCP (06/17/87)
Subject: setenv(3) reverses length test
Index: lib/libc/gen/setenv.c 4.3BSD
Description:
A new library routine, setenv(3) was posted as part of the new
ctime(3) package. This routine adds or modifies entries in the
process's environment. It checks to see if the new entry is
longer than the old one, so it can malloc extra space if necessary.
Unfortunately, the test is reversed.
Repeat-By:
Write a program that prints the environment, uses setenv(3) and
prints it again. Notice that the variable immediately after the
one you modify can get overwritten.
Fix:
The following is a fixed /usr/src/lib/libc/gen/setenv.c.
... cut here ...
/*
* Copyright (c) 1987 Regents of the University of California.
* This file may be freely redistributed provided that this
* notice remains attached.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)setenv.c 1.3 (Berkeley) 6/16/87";
#endif LIBC_SCCS and not lint
#include <sys/types.h>
#include <stdio.h>
/*
* setenv(name,value,rewrite)
* Set the value of the environmental variable "name" to be
* "value". If rewrite is set, replace any current value.
*/
setenv(name,value,rewrite)
register char *name,
*value;
int rewrite;
{
extern char **environ;
static int alloced; /* if allocated space before */
register char *C;
int l_value,
offset;
char *malloc(), *realloc(), *_findenv();
if (*value == '=') /* no `=' in value */
++value;
l_value = strlen(value);
if ((C = _findenv(name,&offset))) { /* find if already exists */
if (!rewrite)
return(0);
if (strlen(C) >= l_value) { /* old larger; copy over */
while (*C++ = *value++);
return(0);
}
}
else { /* create new slot */
register int cnt;
register char **P;
for (P = environ,cnt = 0;*P;++P,++cnt);
if (alloced) { /* just increase size */
environ = (char **)realloc((char *)environ,
(u_int)(sizeof(char *) * (cnt + 2)));
if (!environ)
return(-1);
}
else { /* get new space */
alloced = 1; /* copy old entries into it */
P = (char **)malloc((u_int)(sizeof(char *) *
(cnt + 2)));
if (!P)
return(-1);
bcopy(environ,P,cnt * sizeof(char *));
environ = P;
}
environ[cnt + 1] = NULL;
offset = cnt;
}
for (C = name;*C && *C != '=';++C); /* no `=' in name */
if (!(environ[offset] = /* name + `=' + value */
malloc((u_int)((int)(C - name) + l_value + 2))))
return(-1);
for (C = environ[offset];(*C = *name++) && *C != '=';++C);
for (*C++ = '=';*C++ = *value++;);
return(0);
}
/*
* unsetenv(name) --
* Delete environmental variable "name".
*/
void
unsetenv(name)
char *name;
{
extern char **environ;
register char **P;
int offset;
while (_findenv(name,&offset)) /* if set multiple times */
for (P = &environ[offset];;++P)
if (!(*P = *(P + 1)))
break;
}