Coverage Report

Created: 2026-03-08 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pdns/pdns/burtle.hh
Line
Count
Source
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
23
#pragma once
24
25
#include <cinttypes>
26
27
inline void burtlemix(uint32_t& a, uint32_t& b, uint32_t& c)
28
1.37M
{
29
1.37M
  a -= b;
30
1.37M
  a -= c;
31
1.37M
  a ^= (c >> 13);
32
1.37M
  b -= c;
33
1.37M
  b -= a;
34
1.37M
  b ^= (a << 8);
35
1.37M
  c -= a;
36
1.37M
  c -= b;
37
1.37M
  c ^= (b >> 13);
38
1.37M
  a -= b;
39
1.37M
  a -= c;
40
1.37M
  a ^= (c >> 12);
41
1.37M
  b -= c;
42
1.37M
  b -= a;
43
1.37M
  b ^= (a << 16);
44
1.37M
  c -= a;
45
1.37M
  c -= b;
46
1.37M
  c ^= (b >> 5);
47
1.37M
  a -= b;
48
1.37M
  a -= c;
49
1.37M
  a ^= (c >> 3);
50
1.37M
  b -= c;
51
1.37M
  b -= a;
52
1.37M
  b ^= (a << 10);
53
1.37M
  c -= a;
54
1.37M
  c -= b;
55
1.37M
  c ^= (b >> 15);
56
1.37M
}
57
58
inline uint32_t burtle(const unsigned char* k, uint32_t length, uint32_t initval)
59
35.8k
{
60
35.8k
  uint32_t a, b, c, len;
61
62
  /* Set up the internal state */
63
35.8k
  len = length;
64
35.8k
  a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
65
35.8k
  c = initval; /* the previous hash value */
66
67
  /*---------------------------------------- handle most of the key */
68
999k
  while (len >= 12) {
69
963k
    a += (k[0] + ((uint32_t)k[1] << 8) + ((uint32_t)k[2] << 16) + ((uint32_t)k[3] << 24));
70
963k
    b += (k[4] + ((uint32_t)k[5] << 8) + ((uint32_t)k[6] << 16) + ((uint32_t)k[7] << 24));
71
963k
    c += (k[8] + ((uint32_t)k[9] << 8) + ((uint32_t)k[10] << 16) + ((uint32_t)k[11] << 24));
72
963k
    burtlemix(a, b, c);
73
963k
    k += 12;
74
963k
    len -= 12;
75
963k
  }
76
77
  /*------------------------------------- handle the last 11 bytes */
78
35.8k
  c += length;
79
35.8k
  switch (len) { /* all the case statements fall through */
80
2.08k
  case 11:
81
2.08k
    c += ((uint32_t)k[10] << 24);
82
    /* fall-through */
83
8.67k
  case 10:
84
8.67k
    c += ((uint32_t)k[9] << 16);
85
    /* fall-through */
86
9.70k
  case 9:
87
9.70k
    c += ((uint32_t)k[8] << 8);
88
    /* the first byte of c is reserved for the length */
89
    /* fall-through */
90
10.6k
  case 8:
91
10.6k
    b += ((uint32_t)k[7] << 24);
92
    /* fall-through */
93
11.8k
  case 7:
94
11.8k
    b += ((uint32_t)k[6] << 16);
95
    /* fall-through */
96
13.2k
  case 6:
97
13.2k
    b += ((uint32_t)k[5] << 8);
98
    /* fall-through */
99
14.7k
  case 5:
100
14.7k
    b += k[4];
101
    /* fall-through */
102
26.9k
  case 4:
103
26.9k
    a += ((uint32_t)k[3] << 24);
104
    /* fall-through */
105
29.5k
  case 3:
106
29.5k
    a += ((uint32_t)k[2] << 16);
107
    /* fall-through */
108
30.8k
  case 2:
109
30.8k
    a += ((uint32_t)k[1] << 8);
110
    /* fall-through */
111
34.4k
  case 1:
112
34.4k
    a += k[0];
113
    /* case 0: nothing left to add */
114
35.8k
  }
115
35.8k
  burtlemix(a, b, c);
116
  /*-------------------------------------------- report the result */
117
35.8k
  return c;
118
35.8k
}
119
120
inline uint32_t burtleCI(const unsigned char* k, uint32_t length, uint32_t initval)
121
3.72k
{
122
3.72k
  uint32_t a, b, c, len;
123
124
  /* Set up the internal state */
125
3.72k
  len = length;
126
3.72k
  a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
127
3.72k
  c = initval; /* the previous hash value */
128
129
  /*---------------------------------------- handle most of the key */
130
377k
  while (len >= 12) {
131
373k
    a += (dns_tolower(k[0]) + ((uint32_t)dns_tolower(k[1]) << 8) + ((uint32_t)dns_tolower(k[2]) << 16) + ((uint32_t)dns_tolower(k[3]) << 24));
132
373k
    b += (dns_tolower(k[4]) + ((uint32_t)dns_tolower(k[5]) << 8) + ((uint32_t)dns_tolower(k[6]) << 16) + ((uint32_t)dns_tolower(k[7]) << 24));
133
373k
    c += (dns_tolower(k[8]) + ((uint32_t)dns_tolower(k[9]) << 8) + ((uint32_t)dns_tolower(k[10]) << 16) + ((uint32_t)dns_tolower(k[11]) << 24));
134
373k
    burtlemix(a, b, c);
135
373k
    k += 12;
136
373k
    len -= 12;
137
373k
  }
138
139
  /*------------------------------------- handle the last 11 bytes */
140
3.72k
  c += length;
141
3.72k
  switch (len) { /* all the case statements fall through */
142
54
  case 11:
143
54
    c += ((uint32_t)dns_tolower(k[10]) << 24);
144
    /* fall-through */
145
112
  case 10:
146
112
    c += ((uint32_t)dns_tolower(k[9]) << 16);
147
    /* fall-through */
148
146
  case 9:
149
146
    c += ((uint32_t)dns_tolower(k[8]) << 8);
150
    /* the first byte of c is reserved for the length */
151
    /* fall-through */
152
268
  case 8:
153
268
    b += ((uint32_t)dns_tolower(k[7]) << 24);
154
    /* fall-through */
155
362
  case 7:
156
362
    b += ((uint32_t)dns_tolower(k[6]) << 16);
157
    /* fall-through */
158
438
  case 6:
159
438
    b += ((uint32_t)dns_tolower(k[5]) << 8);
160
    /* fall-through */
161
498
  case 5:
162
498
    b += dns_tolower(k[4]);
163
    /* fall-through */
164
902
  case 4:
165
902
    a += ((uint32_t)dns_tolower(k[3]) << 24);
166
    /* fall-through */
167
1.03k
  case 3:
168
1.03k
    a += ((uint32_t)dns_tolower(k[2]) << 16);
169
    /* fall-through */
170
1.07k
  case 2:
171
1.07k
    a += ((uint32_t)dns_tolower(k[1]) << 8);
172
    /* fall-through */
173
3.59k
  case 1:
174
3.59k
    a += dns_tolower(k[0]);
175
    /* case 0: nothing left to add */
176
3.72k
  }
177
3.72k
  burtlemix(a, b, c);
178
  /*-------------------------------------------- report the result */
179
3.72k
  return c;
180
3.72k
}
181
182
template <typename T>
183
inline uint32_t burtleCI(const T& k, uint32_t initval)
184
0
{
185
0
  return burtleCI(reinterpret_cast<const unsigned char*>(k.data()), k.length(), initval); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast): can't static_cast because of sign difference
186
0
}
Unexecuted instantiation: unsigned int burtleCI<boost::container::basic_string<char, std::__1::char_traits<char>, void> >(boost::container::basic_string<char, std::__1::char_traits<char>, void> const&, unsigned int)
Unexecuted instantiation: unsigned int burtleCI<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned int)