Coverage Report

Created: 2026-03-31 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/lib/server/section.c
Line
Count
Source
1
/*
2
 *   This program is free software; you can redistribute it and/or modify
3
 *   it under the terms of the GNU General Public License as published by
4
 *   the Free Software Foundation; either version 2 of the License, or
5
 *   (at your option) any later version.
6
 *
7
 *   This program is distributed in the hope that it will be useful,
8
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 *   GNU General Public License for more details.
11
 *
12
 *   You should have received a copy of the GNU General Public License
13
 *   along with this program; if not, write to the Free Software
14
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15
 */
16
17
/**
18
 * $Id: 9cd81fe1998a541c6d12744e5f27e1b295e40328 $
19
 *
20
 * @file lib/server/section.c
21
 * @brief Comparison functions for sections
22
 *
23
 * @copyright 2024 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24
 */
25
RCSID("$Id: 9cd81fe1998a541c6d12744e5f27e1b295e40328 $")
26
27
#include <freeradius-devel/server/section.h>
28
29
#define IDENT_ANY_CMP(_a, _b) \
30
0
  (((_a) == CF_IDENT_ANY) < ((_b) == CF_IDENT_ANY)) - (((_a) == CF_IDENT_ANY) > ((_b) == CF_IDENT_ANY))
31
32
#define NULL_CMP(_a, _b) \
33
0
  (((_a) == NULL) < ((_b) == NULL)) - (((_a) == NULL) > ((_b) == NULL))
34
35
/** Compare two sections
36
 *
37
 * - Sections are sorted by name1, then name2.
38
 * - NULLs sort before non-NULLs.
39
 * - CF_IDENT_ANY sort after non-CF_IDENT_ANY.
40
 * - Any other comparisons are lexicographic.
41
 *
42
 * @param[in] one   First section name.
43
 * @param[in] two   Second section name.
44
 *
45
 * @return < 0 if one < two, 0 if one == two, > 0 if one > two.
46
 */
47
int8_t section_name_cmp(void const *one, void const *two)
48
0
{
49
0
  section_name_t const *a = one;
50
0
  section_name_t const *b = two;
51
0
  int ret;
52
53
  /*
54
   *  name1 isn't allowed to be NULL, for wildcard matches
55
   *  we use CF_IDENT_ANY.
56
   */
57
0
  fr_assert(a->name1 && b->name1);
58
59
  /*
60
   *  Straight comparison between sections.
61
   */
62
0
  ret = CMP(a, b);
63
0
  if (ret == 0) return 0;
64
65
  /*
66
   *  Fastpath for static strings and CF_IDENT_ANY
67
   */
68
0
  if (a->name1 == b->name1) goto name2;
69
70
  /*
71
   *  If either identifier is CF_IDENT_ANY, we can't strcmp.
72
   */
73
0
  if ((a->name1 == CF_IDENT_ANY) || (b->name1 == CF_IDENT_ANY)) {
74
0
    ret = IDENT_ANY_CMP(b->name1, a->name1);
75
0
    if (ret != 0) return ret;
76
0
  } else {
77
0
    ret = strcmp(a->name1, b->name1);
78
0
    if (ret != 0) return CMP(ret, 0);
79
0
  }
80
81
0
name2:
82
  /*
83
   *  Second identifier can be NULL.
84
   *
85
   *  NULL name2s sort first.
86
   */
87
0
  ret = NULL_CMP(a->name2, b->name2);
88
0
  if (ret != 0) return ret;
89
90
0
  if (a->name2 == b->name2) return 0;
91
92
0
  if ((a->name2 == CF_IDENT_ANY) || (b->name2 == CF_IDENT_ANY)) {
93
0
    return IDENT_ANY_CMP(b->name2, a->name2); /* Can't strcmp */
94
0
  }
95
96
0
  return CMP(strcmp(a->name2, b->name2), 0);
97
0
}