Coverage Report

Created: 2025-07-11 06:57

/src/sudo/plugins/sudoers/gc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * SPDX-License-Identifier: ISC
3
 *
4
 * Copyright (c) 2016 Todd C. Miller <Todd.Miller@sudo.ws>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
/*
20
 * This is an open source non-commercial project. Dear PVS-Studio, please check it.
21
 * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
22
 */
23
24
#include <config.h>
25
26
#include <stdlib.h>
27
#include <string.h>
28
29
#include <sudoers.h>
30
31
struct sudoers_gc_entry {
32
    SLIST_ENTRY(sudoers_gc_entry) entries;
33
    enum sudoers_gc_types type;
34
    union {
35
  char **vec;
36
  void *ptr;
37
    } u;
38
};
39
SLIST_HEAD(sudoers_gc_list, sudoers_gc_entry);
40
#ifdef NO_LEAKS
41
static struct sudoers_gc_list sudoers_gc_list =
42
    SLIST_HEAD_INITIALIZER(sudoers_gc_list);
43
#endif
44
45
bool
46
sudoers_gc_add(enum sudoers_gc_types type, void *v)
47
397k
{
48
397k
#ifdef NO_LEAKS
49
397k
    struct sudoers_gc_entry *gc;
50
397k
    debug_decl(sudoers_gc_add, SUDOERS_DEBUG_UTIL);
51
52
397k
    if (v == NULL)
53
0
  debug_return_bool(false);
54
55
397k
    gc = calloc(1, sizeof(*gc));
56
397k
    if (gc == NULL) {
57
0
  sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
58
0
  debug_return_bool(false);
59
0
    }
60
397k
    switch (type) {
61
383k
    case GC_PTR:
62
383k
  gc->u.ptr = v;
63
383k
  break;
64
14.0k
    case GC_VECTOR:
65
14.0k
  gc->u.vec = v;
66
14.0k
  break;
67
0
    default:
68
0
  free(gc);
69
0
  sudo_warnx("unexpected garbage type %d", type);
70
0
  debug_return_bool(false);
71
397k
    }
72
397k
    gc->type = type;
73
397k
    SLIST_INSERT_HEAD(&sudoers_gc_list, gc, entries);
74
397k
    debug_return_bool(true);
75
#else
76
    return true;
77
#endif /* NO_LEAKS */
78
397k
}
79
80
bool
81
sudoers_gc_remove(enum sudoers_gc_types type, void *v)
82
147k
{
83
147k
#ifdef NO_LEAKS
84
147k
    struct sudoers_gc_entry *gc, *prev = NULL;
85
147k
    debug_decl(sudoers_gc_remove, SUDOERS_DEBUG_UTIL);
86
87
147k
    if (v == NULL)
88
82.5k
  debug_return_bool(false);
89
90
713k
    SLIST_FOREACH(gc, &sudoers_gc_list, entries) {
91
713k
  switch (gc->type) {
92
682k
  case GC_PTR:
93
682k
      if (gc->u.ptr == v)
94
59.0k
        goto found;
95
623k
      break;
96
623k
  case GC_VECTOR:
97
30.5k
      if (gc->u.vec == v)
98
6.00k
        goto found;
99
24.5k
      break;
100
24.5k
  default:
101
0
      sudo_warnx("unexpected garbage type %d in %p", gc->type, gc);
102
713k
  }
103
648k
  prev = gc;
104
648k
    }
105
    /* If this happens, there is a bug in the g/c code. */
106
0
    sudo_warnx("%s: unable to find %p, type %d", __func__, v, type);
107
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
108
0
    abort();
109
#else
110
    debug_return_bool(false);
111
#endif
112
65.0k
found:
113
65.0k
    if (prev == NULL)
114
11.8k
  SLIST_REMOVE_HEAD(&sudoers_gc_list, entries);
115
53.1k
    else
116
53.1k
  SLIST_REMOVE_AFTER(prev, entries);
117
65.0k
    free(gc);
118
119
65.0k
    debug_return_bool(true);
120
#else
121
    return true;
122
#endif /* NO_LEAKS */
123
65.0k
}
124
125
void
126
sudoers_gc_run(void)
127
26.8k
{
128
26.8k
#ifdef NO_LEAKS
129
26.8k
    struct sudoers_gc_entry *gc;
130
26.8k
    char **cur;
131
26.8k
    debug_decl(sudoers_gc_run, SUDOERS_DEBUG_UTIL);
132
133
    /* Collect garbage. */
134
359k
    while ((gc = SLIST_FIRST(&sudoers_gc_list)) != NULL) {
135
332k
  SLIST_REMOVE_HEAD(&sudoers_gc_list, entries);
136
332k
  switch (gc->type) {
137
324k
  case GC_PTR:
138
324k
      free(gc->u.ptr);
139
324k
      free(gc);
140
324k
      break;
141
8.05k
  case GC_VECTOR:
142
285k
      for (cur = gc->u.vec; *cur != NULL; cur++)
143
277k
    free(*cur);
144
8.05k
      free(gc->u.vec);
145
8.05k
      free(gc);
146
8.05k
      break;
147
0
  default:
148
0
      sudo_warnx("unexpected garbage type %d", gc->type);
149
332k
  }
150
332k
    }
151
152
26.8k
    debug_return;
153
26.8k
#endif /* NO_LEAKS */
154
26.8k
}