Coverage Report

Created: 2025-07-23 07:04

/src/samba/lib/fuzzing/fuzz_strncasecmp_ldb.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   Fuzzing ldb_comparison_fold()
3
   Copyright (C) Catalyst IT 2020
4
5
   This program is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 3 of the License, or
8
   (at your option) any later version.
9
10
   This program is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU General Public License for more details.
14
15
   You should have received a copy of the GNU General Public License
16
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
#include "includes.h"
19
#include "fuzzing/fuzzing.h"
20
#include "charset.h"
21
22
23
int LLVMFuzzerInitialize(int *argc, char ***argv)
24
372
{
25
372
  return 0;
26
372
}
27
28
29
int LLVMFuzzerTestOneInput(const uint8_t *input, size_t len)
30
574
{
31
574
  struct ldb_val v[3] = {{},{},{}};
32
574
  size_t i, j, k;
33
574
  int results[9], ab, ac, bc;
34
35
574
  if (len < 3) {
36
2
    return 0;
37
2
  }
38
39
572
  j = 0;
40
572
  k = 0;
41
572
  v[j].data = discard_const(input);
42
43
  /*
44
   * We split the input into 3 ldb_vals, on the byte '*' (42), chosen
45
   * because it is *not* special with regard to termination, utf-8, or
46
   * casefolding.
47
   *
48
   * if there are not 2 '*' bytes, the last value[s] will be empty, with
49
   * a NULL pointer and zero length.
50
   */
51
52
16.7M
  for (i = 0; i < len; i++) {
53
16.7M
    if (input[i] != '*') {
54
16.7M
      continue;
55
16.7M
    }
56
906
    v[j].length = i - k;
57
906
    i++;
58
906
    j++;
59
906
    if (j > 2 || i == len) {
60
537
      break;
61
537
    }
62
369
    k = i;
63
369
    v[j].data = discard_const(input + k);
64
369
  }
65
66
2.28k
  for (i = 0; i < 3; i++) {
67
1.71k
    char *s1 = (char*)v[i].data;
68
1.71k
    size_t len1 = v[i].length;
69
6.86k
    for (j = 0; j < 3; j++) {
70
5.14k
      char *s2 = (char*)v[j].data;
71
5.14k
      size_t len2 = v[j].length;
72
5.14k
      int r = strncasecmp_ldb(s1, len1, s2, len2);
73
5.14k
      if (abs(r) > 1) {
74
0
        abort();
75
0
      }
76
5.14k
      results[i * 3 + j] = r;
77
5.14k
    }
78
1.71k
  }
79
80
  /*
81
   * There are nine comparisons we make.
82
   *
83
   *    A B C
84
   *  A = x x
85
   *  B - = x
86
   *  C - - =
87
   *
88
   * The diagonal should be all zeros (A == A, etc)
89
   * The upper and lower triangles should complement each other
90
   * (A > B implies B < A; A == B implies B == A).
91
   *
92
   * So we check for those identities first.
93
   */
94
95
572
  if ((results[0] != 0) ||
96
572
      (results[4] != 0) ||
97
572
      (results[8] != 0)) {
98
0
    abort();
99
0
  }
100
101
572
  ab = results[3];
102
572
  ac = results[6];
103
572
  bc = results[7];
104
105
572
  if (ab != -results[1] ||
106
572
      ac != -results[2] ||
107
572
      bc != -results[5]) {
108
0
    abort();
109
0
  }
110
111
   /*
112
   * Then there are 27 states within the three comparisons of one
113
   * triangle, because each of AB, AC, and BC can be in 3 states.
114
   *
115
   *  0    (A < B) (A < C) (B < C)   A < B < C
116
   *  1    (A < B) (A < C) (B = C)   A < (B|C)
117
   *  2    (A < B) (A < C) (B > C)   A < C < B
118
   *  3    (A < B) (A = C) (B < C)    invalid
119
   *  4    (A < B) (A = C) (B = C)    invalid
120
   *  5    (A < B) (A = C) (B > C)   (A|C) < B
121
   *  6    (A < B) (A > C) (B < C)    invalid
122
   *  7    (A < B) (A > C) (B = C)    invalid
123
   *  8    (A < B) (A > C) (B > C)   C < A < B
124
   *  9    (A = B) (A < C) (B < C)   (A|B) < C
125
   * 10    (A = B) (A < C) (B = C)    invalid
126
   * 11    (A = B) (A < C) (B > C)    invalid
127
   * 12    (A = B) (A = C) (B < C)    invalid
128
   * 13    (A = B) (A = C) (B = C)   A = B = C
129
   * 14    (A = B) (A = C) (B > C)    invalid
130
   * 15    (A = B) (A > C) (B < C)    invalid
131
   * 16    (A = B) (A > C) (B = C)    invalid
132
   * 17    (A = B) (A > C) (B > C)   C < (A|B)
133
   * 18    (A > B) (A < C) (B < C)   B < C < A
134
   * 19    (A > B) (A < C) (B = C)    invalid
135
   * 20    (A > B) (A < C) (B > C)    invalid
136
   * 21    (A > B) (A = C) (B < C)   B < (A|C)
137
   * 22    (A > B) (A = C) (B = C)    invalid
138
   * 23    (A > B) (A = C) (B > C)    invalid
139
   * 24    (A > B) (A > C) (B < C)   B < C < A
140
   * 25    (A > B) (A > C) (B = C)   (B|C) < A
141
   * 26    (A > B) (A > C) (B > C)   C < B < A
142
   *
143
   * It actually turns out to be quite simple:
144
   */
145
146
572
  if (ab == 0) {
147
85
    if (ac != bc) {
148
0
      abort();
149
0
    }
150
487
  } else if (ab < 0) {
151
400
    if (ac >= 0 && bc <= 0) {
152
0
      abort();
153
0
    }
154
400
  } else {
155
87
    if (ac <= 0 && bc >= 0) {
156
0
      abort();
157
0
    }
158
87
  }
159
160
572
  return 0;
161
572
}