Coverage Report

Created: 2025-04-22 06:14

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