Coverage Report

Created: 2026-01-10 06:49

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.58M
{
31
9.58M
    size_t len, sep_pos;
32
9.58M
    bool iswild = false, match = false;
33
9.58M
    bool saw_sep = false;
34
9.58M
    const char *cp;
35
9.58M
    debug_decl(matches_env_pattern, SUDOERS_DEBUG_ENV);
36
37
    /* Locate position of the '=' separator in var=value. */
38
9.58M
    sep_pos = strcspn(var, "=");
39
40
    /* Locate '*' wildcard and compute len. */
41
79.0M
    for (cp = pattern; *cp != '\0'; cp++) {
42
70.0M
  if (*cp == '*') {
43
574k
      iswild = true;
44
574k
      break;
45
574k
  }
46
70.0M
    }
47
9.58M
    len = (size_t)(cp - pattern);
48
49
9.58M
    if (iswild) {
50
  /* Match up to the '*' wildcard. */
51
574k
  if (strncmp(pattern, var, len) == 0) {
52
44.5k
      while (*cp != '\0') {
53
44.5k
    if (*cp == '*') {
54
        /* Collapse sequential '*'s */
55
25.8k
        do {
56
25.8k
      cp++;
57
25.8k
        } while (*cp == '*');
58
        /* A '*' at the end of a pattern matches anything. */
59
25.8k
        if (*cp == '\0') {
60
7.04k
      match = true;
61
7.04k
      break;
62
7.04k
        }
63
        /* Keep track of whether we matched an equal sign. */
64
18.7k
        if (*cp == '=')
65
18.7k
      saw_sep = true;
66
        /* Look for first match of text after the '*' */
67
217k
        while ((saw_sep || len != sep_pos) &&
68
217k
      var[len] != '\0' && var[len] != *cp)
69
198k
      len++;
70
18.7k
    }
71
37.5k
    if (var[len] != *cp)
72
18.7k
        break;
73
18.7k
    cp++;
74
18.7k
    len++;
75
18.7k
      }
76
25.8k
      if (*cp == '\0' && (len == sep_pos || var[len] == '\0'))
77
1.02k
    match = true;
78
25.8k
  }
79
9.01M
    } else {
80
9.01M
  if (strncmp(pattern, var, len) == 0 &&
81
51.4k
      (len == sep_pos || var[len] == '\0')) {
82
50.9k
      match = true;
83
50.9k
  }
84
9.01M
    }
85
9.58M
    if (match)
86
58.0k
  *full_match = len > sep_pos + 1;
87
    debug_return_bool(match);
88
9.58M
}