Coverage Report

Created: 2026-06-07 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nspr/pr/src/misc/prenv.c
Line
Count
Source
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include <string.h>
6
#include <stdlib.h>
7
#include "primpl.h"
8
#include "prmem.h"
9
10
#if defined(XP_UNIX)
11
#  include <unistd.h>
12
#  if defined(DARWIN)
13
#    if defined(HAVE_CRT_EXTERNS_H)
14
#      include <crt_externs.h>
15
#    endif /* HAVE_CRT_EXTERNS_H */
16
#  else    /* DARWIN */
17
PR_IMPORT_DATA(char**) environ;
18
#  endif   /* DARWIN */
19
#endif     /* XP_UNIX */
20
21
#if !defined(HAVE_SECURE_GETENV) && defined(HAVE___SECURE_GETENV)
22
#  define secure_getenv __secure_getenv
23
#  define HAVE_SECURE_GETENV 1
24
#endif
25
26
/* Lock used to lock the environment */
27
#if defined(_PR_NO_PREEMPT)
28
#  define _PR_NEW_LOCK_ENV()
29
#  define _PR_DELETE_LOCK_ENV()
30
#  define _PR_LOCK_ENV()
31
#  define _PR_UNLOCK_ENV()
32
#elif defined(_PR_LOCAL_THREADS_ONLY)
33
extern _PRCPU* _pr_primordialCPU;
34
static PRIntn _is;
35
#  define _PR_NEW_LOCK_ENV()
36
#  define _PR_DELETE_LOCK_ENV()
37
#  define _PR_LOCK_ENV() \
38
    if (_pr_primordialCPU) _PR_INTSOFF(_is);
39
#  define _PR_UNLOCK_ENV() \
40
    if (_pr_primordialCPU) _PR_INTSON(_is);
41
#else
42
static PRLock* _pr_envLock = NULL;
43
#  define _PR_NEW_LOCK_ENV() \
44
15
    { _pr_envLock = PR_NewLock(); }
45
#  define _PR_DELETE_LOCK_ENV()      \
46
0
    {                                \
47
0
      if (_pr_envLock) {             \
48
0
        PR_DestroyLock(_pr_envLock); \
49
0
        _pr_envLock = NULL;          \
50
0
      }                              \
51
0
    }
52
#  define _PR_LOCK_ENV()                     \
53
104k
    {                                        \
54
104k
      if (_pr_envLock) PR_Lock(_pr_envLock); \
55
104k
    }
56
#  define _PR_UNLOCK_ENV()                     \
57
104k
    {                                          \
58
104k
      if (_pr_envLock) PR_Unlock(_pr_envLock); \
59
104k
    }
60
#endif
61
62
/************************************************************************/
63
64
15
void _PR_InitEnv(void) { _PR_NEW_LOCK_ENV(); }
65
66
0
void _PR_CleanupEnv(void) { _PR_DELETE_LOCK_ENV(); }
67
68
210
PR_IMPLEMENT(char*) PR_GetEnv(const char* var) {
69
210
  char* ev;
70
71
210
  if (!_pr_initialized) {
72
0
    _PR_ImplicitInitialization();
73
0
  }
74
75
210
  _PR_LOCK_ENV();
76
210
  ev = _PR_MD_GET_ENV(var);
77
210
  _PR_UNLOCK_ENV();
78
210
  return ev;
79
210
}
80
81
104k
PR_IMPLEMENT(char*) PR_GetEnvSecure(const char* var) {
82
104k
#ifdef HAVE_SECURE_GETENV
83
104k
  char* ev;
84
85
104k
  if (!_pr_initialized) {
86
1
    _PR_ImplicitInitialization();
87
1
  }
88
89
104k
  _PR_LOCK_ENV();
90
104k
  ev = secure_getenv(var);
91
104k
  _PR_UNLOCK_ENV();
92
93
104k
  return ev;
94
#else
95
#  ifdef XP_UNIX
96
  /*
97
  ** Fall back to checking uids and gids.  This won't detect any other
98
  ** privilege-granting mechanisms the platform may have.  This also
99
  ** can't detect the case where the process already called
100
  ** setuid(geteuid()) and/or setgid(getegid()).
101
  */
102
  if (getuid() != geteuid() || getgid() != getegid()) {
103
    return NULL;
104
  }
105
#  endif /* XP_UNIX */
106
  return PR_GetEnv(var);
107
#endif   /* HAVE_SECURE_GETENV */
108
104k
}
109
110
0
PR_IMPLEMENT(PRStatus) PR_SetEnv(const char* string) {
111
0
  PRIntn result;
112
113
0
  if (!_pr_initialized) {
114
0
    _PR_ImplicitInitialization();
115
0
  }
116
117
0
  if (!strchr(string, '=')) {
118
0
    return (PR_FAILURE);
119
0
  }
120
121
0
  _PR_LOCK_ENV();
122
0
  result = _PR_MD_PUT_ENV((char*)string);
123
0
  _PR_UNLOCK_ENV();
124
0
  return result ? PR_FAILURE : PR_SUCCESS;
125
0
}
126
127
#if defined(XP_UNIX) && (!defined(DARWIN) || defined(HAVE_CRT_EXTERNS_H))
128
0
PR_IMPLEMENT(char**) PR_DuplicateEnvironment(void) {
129
0
  char **the_environ, **result, **end, **src, **dst;
130
131
0
  _PR_LOCK_ENV();
132
#  ifdef DARWIN
133
  the_environ = *(_NSGetEnviron());
134
#  else
135
0
  the_environ = environ;
136
0
#  endif
137
138
0
  for (end = the_environ; *end != NULL; end++) /* empty loop body */;
139
140
0
  result = (char**)PR_Malloc(sizeof(char*) * (end - the_environ + 1));
141
0
  if (result != NULL) {
142
0
    for (src = the_environ, dst = result; src != end; src++, dst++) {
143
0
      size_t len;
144
145
0
      len = strlen(*src) + 1;
146
0
      *dst = PR_Malloc(len);
147
0
      if (*dst == NULL) {
148
        /* Allocation failed.  Must clean up the half-copied env. */
149
0
        char** to_delete;
150
151
0
        for (to_delete = result; to_delete != dst; to_delete++) {
152
0
          PR_Free(*to_delete);
153
0
        }
154
0
        PR_Free(result);
155
0
        result = NULL;
156
0
        goto out;
157
0
      }
158
0
      memcpy(*dst, *src, len);
159
0
    }
160
0
    *dst = NULL;
161
0
  }
162
0
out:
163
0
  _PR_UNLOCK_ENV();
164
0
  return result;
165
0
}
166
#else
167
/* This platform doesn't support raw access to the environ block. */
168
PR_IMPLEMENT(char**) PR_DuplicateEnvironment(void) { return NULL; }
169
#endif