getopt: fix null pointer arithmetic ub
[musl] / src / env / putenv.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4
5 static void dummy(char *old, char *new) {}
6 weak_alias(dummy, __env_rm_add);
7
8 int __putenv(char *s, size_t l, char *r)
9 {
10         size_t i=0;
11         if (__environ) {
12                 for (char **e = __environ; *e; e++, i++)
13                         if (!strncmp(s, *e, l+1)) {
14                                 char *tmp = *e;
15                                 *e = s;
16                                 __env_rm_add(tmp, r);
17                                 return 0;
18                         }
19         }
20         static char **oldenv;
21         char **newenv;
22         if (__environ == oldenv) {
23                 newenv = realloc(oldenv, sizeof *newenv * (i+2));
24                 if (!newenv) goto oom;
25         } else {
26                 newenv = malloc(sizeof *newenv * (i+2));
27                 if (!newenv) goto oom;
28                 if (i) memcpy(newenv, __environ, sizeof *newenv * i);
29                 free(oldenv);
30         }
31         newenv[i] = s;
32         newenv[i+1] = 0;
33         __environ = oldenv = newenv;
34         if (r) __env_rm_add(0, r);
35         return 0;
36 oom:
37         free(r);
38         return -1;
39 }
40
41 int putenv(char *s)
42 {
43         size_t l = __strchrnul(s, '=') - s;
44         if (!l || !s[l]) return unsetenv(s);
45         return __putenv(s, l, 0);
46 }