Coverage Report

Created: 2026-02-14 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/sudo/plugins/sudoers/env_pattern.c
Line
Count
Source
1
/*
2
 * SPDX-License-Identifier: ISC
3
 *
4
 * Copyright (c) 2017 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
/* extern for regress tests */
28
bool
29
matches_env_pattern(const char *pattern, const char *var, bool *full_match)
30
9.45M
{
31
9.45M
    size_t len, sep_pos;
32
9.45M
    bool iswild = false, match = false;
33
9.45M
    bool saw_sep = false;
34
9.45M
    const char *cp;
35
9.45M
    debug_decl(matches_env_pattern, SUDOERS_DEBUG_ENV);
36
37
    /* Locate position of the '=' separator in var=value. */
38
9.45M
    sep_pos = strcspn(var, "=");
39
40
    /* Locate '*' wildcard and compute len. */
41
78.0M
    for (cp = pattern; *cp != '\0'; cp++) {
42
69.1M
  if (*cp == '*') {
43
564k
      iswild = true;
44
564k
      break;
45
564k
  }
46
69.1M
    }
47
9.45M
    len = (size_t)(cp - pattern);
48
49
9.45M
    if (iswild) {
50
  /* Match up to the '*' wildcard. */
51
564k
  if (strncmp(pattern, var, len) == 0) {
52
40.5k
      while (*cp != '\0') {
53
40.5k
    if (*cp == '*') {
54
        /* Collapse sequential '*'s */
55
21.8k
        do {
56
21.8k
      cp++;
57
21.8k
        } while (*cp == '*');
58
        /* A '*' at the end of a pattern matches anything. */
59
21.8k
        if (*cp == '\0') {
60
3.26k
      match = true;
61
3.26k
      break;
62
3.26k
        }
63
        /* Keep track of whether we matched an equal sign. */
64
18.6k
        if (*cp == '=')
65
18.6k
      saw_sep = true;
66
        /* Look for first match of text after the '*' */
67
215k
        while ((saw_sep || len != sep_pos) &&
68
215k
      var[len] != '\0' && var[len] != *cp)
69
196k
      len++;
70
18.6k
    }
71
37.2k
    if (var[len] != *cp)
72
18.6k
        break;
73
18.6k
    cp++;
74
18.6k
    len++;
75
18.6k
      }
76
21.8k
      if (*cp == '\0' && (len == sep_pos || var[len] == '\0'))
77
936
    match = true;
78
21.8k
  }
79
8.89M
    } else {
80
8.89M
  if (strncmp(pattern, var, len) == 0 &&
81
46.8k
      (len == sep_pos || var[len] == '\0')) {
82
46.5k
      match = true;
83
46.5k
  }
84
8.89M
    }
85
9.45M
    if (match)
86
49.7k
  *full_match = len > sep_pos + 1;
87
    debug_return_bool(match);
88
9.45M
}