Coverage Report

Created: 2025-11-11 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/sudo/plugins/sudoers/serialize_list.c
Line
Count
Source
1
/*
2
 * SPDX-License-Identifier: ISC
3
 *
4
 * Copyright (c) 2019, 2022 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
#include <config.h>
20
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
25
#include <sudoers.h>
26
27
/*
28
 * Convert struct list_members to a comma-separated string with
29
 * the given variable name.  Escapes backslashes and commas.
30
 */
31
char *
32
serialize_list(const char *varname, struct list_members *members)
33
22.3k
{
34
22.3k
    struct list_member *lm, *next;
35
22.3k
    size_t len, result_size;
36
22.3k
    char *cp, *result;
37
22.3k
    debug_decl(serialize_list, SUDOERS_DEBUG_PLUGIN);
38
39
22.3k
    result_size = strlen(varname) + 1;
40
22.3k
    SLIST_FOREACH(lm, members, entries) {
41
314k
  for (cp = lm->value; *cp != '\0'; cp++) {
42
292k
      result_size++;
43
292k
      if (*cp == '\\' || *cp == ',')
44
0
    result_size++;
45
292k
  }
46
22.3k
  result_size++;
47
22.3k
    }
48
22.3k
    if ((result = malloc(result_size)) == NULL)
49
0
  goto bad;
50
    /* No need to check len for overflow here. */
51
22.3k
    len = strlcpy(result, varname, result_size);
52
22.3k
    result[len++] = '=';
53
22.3k
    SLIST_FOREACH_SAFE(lm, members, entries, next) {
54
314k
  for (cp = lm->value; *cp != '\0'; cp++) {
55
292k
      bool escape = (*cp == '\\' || *cp == ',');
56
292k
      if (len + 1 + escape >= result_size) {
57
0
    sudo_warnx(U_("internal error, %s overflow"), __func__);
58
0
    goto bad;
59
0
      }
60
292k
      if (escape)
61
0
    result[len++] = '\\';
62
292k
      result[len++] = *cp;
63
292k
  }
64
22.3k
  if (next != NULL) {
65
0
      if (len + 1 >= result_size) {
66
0
    sudo_warnx(U_("internal error, %s overflow"), __func__);
67
0
    goto bad;
68
0
      }
69
0
      result[len++] = ',';
70
0
  }
71
22.3k
  result[len] = '\0';
72
22.3k
    }
73
22.3k
    debug_return_str(result);
74
0
bad:
75
0
    free(result);
76
0
    debug_return_str(NULL);
77
0
}