Coverage Report

Created: 2025-11-05 06:39

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