Skip to content

Commit 25784cb

Browse files
committed
Fix first batch of review comments by Wouter
1 parent eebed6c commit 25784cb

File tree

12 files changed

+94
-106
lines changed

12 files changed

+94
-106
lines changed

compat/getopt.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* getopt.h -- some useful comment
2+
* getopt.h -- getopt definitions for platform that are missing unistd.h
33
*
44
* Copyright (c) 2023, NLnet Labs. All rights reserved.
55
*

doc/manual/design_notes.rst

+16
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,22 @@ therefore managed on a per file base.
6161
On-the-fly indexing is a good tradeoff, but does introduce some complexity
6262
with regards to handling partial tokens.
6363

64+
Padded operation
65+
^^^^^^^^^^^^^^^^
66+
67+
The AVX-512 instruction set offers masked load and store operations, earlier
68+
instruction sets, like SSE4.2 and AVX2 do not. |project| requires input
69+
buffers to be sufficiently large enough to ensure optimized operations can
70+
safely load blocks of input data without reading past the buffer limit. This
71+
requirement is of no concern to the user when parsing files as |project|
72+
manages input buffers. The requirement is of concern when the user provides
73+
the input directly as the buffer must be null-terminated and padded.
74+
75+
.. note::
76+
Future releases may lift this requirement by using fallback
77+
implementations for the last set of tokens that are not sufficiently
78+
padded.
79+
6480

6581
Comments
6682
--------

include/zone/attributes.h

-11
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,6 @@
2828
# define zone_attribute(params)
2929
#endif
3030

31-
#if defined __has_attribute
32-
# define zone_has_attribute(params) __has_attribute(params)
33-
# define zone_attribute(params) __attribute__(params)
34-
#elif zone_gcc
35-
# define zone_has_attribute(params) __has_attribute(params)
36-
# define zone_attribute(params) __attribute__(params)
37-
#else
38-
# define zone_has_attribute(params)
39-
# define zone_attribute(params)
40-
#endif
41-
4231
#define zone_nonnull(params) zone_attribute((__nonnull__ params))
4332
#define zone_nonnull_all zone_attribute((__nonnull__))
4433

src/fallback/parser.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
#include "generic/apl.h"
3636
#include "generic/svcb.h"
3737
#include "generic/cert.h"
38-
#include "generic/dnssec.h"
38+
#include "generic/algorithm.h"
3939
#include "generic/types.h"
4040
#include "generic/type.h"
4141
#include "generic/format.h"

src/generic/algorithm.h

+27-34
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/**
2-
* dnssec.h
2+
* algorithm.h -- Algorithm RDATA parser
33
*
44
* Copyright (c) 2023, NLnet Labs. All rights reserved.
55
*
66
* SPDX-License-Identifier: BSD-3-Clause
77
*
88
*/
9-
#ifndef DNSSEC_H
10-
#define DNSSEC_H
9+
#ifndef ALGORITHM_H
10+
#define ALGORITHM_H
1111

1212
// https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
1313

@@ -109,12 +109,8 @@ static uint8_t algorithm_hash(uint64_t value)
109109

110110
nonnull_all
111111
warn_unused_result
112-
static really_inline int32_t parse_algorithm_type(
113-
parser_t *parser,
114-
const type_info_t *type,
115-
const rdata_info_t *field,
116-
rdata_t *rdata,
117-
const token_t *token)
112+
static really_inline int32_t scan_algorithm(
113+
const char *data, size_t length, uint8_t *number)
118114
{
119115
static const int8_t zero_masks[48] = {
120116
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -125,17 +121,15 @@ static really_inline int32_t parse_algorithm_type(
125121
0, 0, 0, 0, 0, 0, 0, 0
126122
};
127123

128-
uint32_t number = (uint8_t)token->data[0] - '0';
129-
130-
if (unlikely(number > 9)) {
124+
if ((uint8_t)*data - '0' > 9) {
131125
uint64_t input;
132-
memcpy(&input, token->data, 8);
126+
memcpy(&input, data, 8);
133127
const uint64_t letter_mask = 0x4040404040404040llu;
134128
// convert to upper case
135-
input &= input & ~((input & letter_mask) >> 1);
129+
input &= ~((input & letter_mask) >> 1);
136130
// zero out non-relevant bytes
137131
uint64_t zero_mask;
138-
memcpy(&zero_mask, &zero_masks[32 - (token->length & 0x1f)], 8);
132+
memcpy(&zero_mask, &zero_masks[32 - (length & 0x1f)], 8);
139133
input &= zero_mask;
140134
const uint8_t index = algorithm_hash(input);
141135
assert(index < 16);
@@ -145,36 +139,35 @@ static really_inline int32_t parse_algorithm_type(
145139
memcpy(&name, algorithm->key.name, 8);
146140
matches = input == name;
147141
// compare bytes 8-15
148-
memcpy(&input, token->data + 8, 8);
142+
memcpy(&input, data + 8, 8);
149143
memcpy(&mask, algorithm_hash_map[index].mask + 8, 8);
150144
memcpy(&name, algorithm->key.name + 8, 8);
151145
matches &= (input & mask) == name;
152146
// compare bytes 16-23
153-
memcpy(&input, token->data + 16, 8);
147+
memcpy(&input, data + 16, 8);
154148
memcpy(&mask, algorithm_hash_map[index].mask + 16, 8);
155149
memcpy(&name, algorithm->key.name + 16, 8);
156150
matches &= (input & mask) == name;
157-
if (!(matches && (token->length == algorithm->key.length) && number > 0))
158-
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
159-
*rdata->octets++ = (uint8_t)algorithm->value;
160-
return 0;
151+
*number = algorithm->value;
152+
return matches & (length == algorithm->key.length) & (*number > 0);
161153
}
162154

163-
bool leading_zero = (number == 0) & (token->length > 1);
164-
size_t length = 1;
165-
166-
for (; length < token->length; length++) {
167-
const uint8_t digit = (uint8_t)token->data[length] - '0';
168-
if (digit > 9)
169-
break;
170-
number = number * 10 + digit;
171-
}
155+
return scan_int8(data, length, number);
156+
}
172157

173-
*rdata->octets++ = (uint8_t)number;
174-
if (number > 255 || length > 3 || length != token->length || leading_zero)
158+
nonnull_all
159+
warn_unused_result
160+
static really_inline int32_t parse_algorithm(
161+
parser_t *parser,
162+
const type_info_t *type,
163+
const rdata_info_t *field,
164+
rdata_t *rdata,
165+
const token_t *token)
166+
{
167+
if (!scan_algorithm(token->data, token->length, rdata->octets))
175168
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
176-
169+
rdata->octets++;
177170
return 0;
178171
}
179172

180-
#endif // DNSSEC_H
173+
#endif // ALGORITHM_H

src/generic/cert.h

+25-35
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,8 @@ static uint8_t certificate_hash(uint64_t value)
6767
}
6868

6969
nonnull_all
70-
static really_inline int32_t parse_certificate_type(
71-
parser_t *parser,
72-
const type_info_t *type,
73-
const rdata_info_t *field,
74-
rdata_t *rdata,
75-
const token_t *token)
70+
static really_inline int32_t scan_certificate_type(
71+
const char *data, size_t length, uint16_t *type)
7672
{
7773
static const int8_t zero_masks[48] = {
7874
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -83,49 +79,43 @@ static really_inline int32_t parse_certificate_type(
8379
0, 0, 0, 0, 0, 0, 0, 0
8480
};
8581

86-
uint32_t number = (uint8_t)token->data[0] - '0';
87-
88-
if (number > 9) {
82+
if ((uint8_t)*data - '0' > 9) {
8983
uint64_t input;
90-
memcpy(&input, token->data, 8);
84+
memcpy(&input, data, 8);
9185
static const uint64_t letter_mask = 0x4040404040404040llu;
92-
const size_t length = token->length;
9386
// convert to upper case
94-
input &= input & ~((input & letter_mask) >> 1);
87+
input &= ~((input & letter_mask) >> 1);
9588
// zero out non-relevant bytes
9689
uint64_t zero_mask;
97-
memcpy(&zero_mask, &zero_masks[32 - (token->length & 0xf)], 8);
90+
memcpy(&zero_mask, &zero_masks[32 - (length & 0xf)], 8);
9891
input &= zero_mask;
9992
const uint8_t index = certificate_hash(input);
10093
assert(index < 16);
10194
const certificate_type_t *certificate_type = certificate_type_map[index];
10295
uint64_t name;
10396
memcpy(&name, certificate_type->key.name, 8);
104-
uint16_t value = certificate_type->value;
105-
if (unlikely((input != name) & (length != certificate_type->key.length) & (value != 0)))
106-
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
107-
value = htobe16(value);
108-
memcpy(rdata->octets, &value, 2);
109-
rdata->octets += 2;
110-
return 0;
111-
}
112-
113-
bool leading_zero = (number == 0) & (token->length > 1);
114-
size_t length = 1;
115-
116-
for (; length < token->length; length++) {
117-
const uint8_t digit = (uint8_t)token->data[length] - '0';
118-
if (digit > 9)
119-
break;
120-
number = number * 10 + digit;
97+
*type = certificate_type->value;
98+
return (input == name) &
99+
(length == certificate_type->key.length) &
100+
(*type != 0);
121101
}
122102

123-
if (number > 65535 || length > 5 || length != token->length || leading_zero)
124-
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
103+
return scan_int16(data, length, type);
104+
}
125105

126-
uint16_t value = (uint16_t)number;
127-
value = htobe16(value);
128-
memcpy(rdata->octets, &value, 2);
106+
nonnull_all
107+
static really_inline int32_t parse_certificate_type(
108+
parser_t *parser,
109+
const type_info_t *type,
110+
const rdata_info_t *field,
111+
rdata_t *rdata,
112+
const token_t *token)
113+
{
114+
uint16_t cert;
115+
if (!scan_certificate_type(token->data, token->length, &cert))
116+
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
117+
cert = htobe16(cert);
118+
memcpy(rdata->octets, &cert, 2);
129119
rdata->octets += 2;
130120
return 0;
131121
}

src/generic/types.h

+19-6
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,7 @@ static int32_t parse_cert_rdata(
12701270
return code;
12711271
if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
12721272
return code;
1273-
if ((code = parse_algorithm_type(parser, type, &fields[2], rdata, token)) < 0)
1273+
if ((code = parse_algorithm(parser, type, &fields[2], rdata, token)) < 0)
12741274
return code;
12751275
take(parser, token);
12761276
if ((code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0)
@@ -1346,7 +1346,7 @@ static int32_t parse_ds_rdata(
13461346
return code;
13471347
if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
13481348
return code;
1349-
if ((code = parse_algorithm_type(parser, type, &fields[1], rdata, token)) < 0)
1349+
if ((code = parse_algorithm(parser, type, &fields[1], rdata, token)) < 0)
13501350
return code;
13511351
if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
13521352
return code;
@@ -1375,7 +1375,7 @@ static int32_t check_sshfp_rr(
13751375

13761376
// https://www.iana.org/assignments/dns-sshfp-rr-parameters
13771377

1378-
if (c >= n)
1378+
if (c == n)
13791379
SYNTAX_ERROR(parser, "Missing %s in %s", NAME((&f[0])), NAME(type));
13801380
else if (o[1] == 1 && (n - c) != 20)
13811381
SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s",
@@ -1398,15 +1398,28 @@ static int32_t parse_sshfp_rdata(
13981398
return code;
13991399
if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0)
14001400
return code;
1401+
1402+
const uint8_t *fingerprint_type = rdata->octets;
14011403
if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
14021404
return code;
14031405
if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
14041406
return code;
1407+
1408+
const uint8_t *fingerprint = rdata->octets;
14051409
take(parser, token);
14061410
if ((code = parse_base16_sequence(parser, type, &fields[2], rdata, token)) < 0)
14071411
return code;
14081412

1409-
return check_sshfp_rr(parser, type, rdata);
1413+
// https://www.iana.org/assignments/dns-sshfp-rr-parameters
1414+
size_t fingerprint_size = (uintptr_t)rdata->octets - (uintptr_t)fingerprint;
1415+
if (unlikely(*fingerprint_type == 1 && fingerprint_size != 20))
1416+
SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s",
1417+
"SHA1", NAME(type));
1418+
if (unlikely(*fingerprint_type == 2 && fingerprint_size != 32))
1419+
SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s",
1420+
"SHA256", NAME(type));
1421+
1422+
return accept_rr(parser, type, rdata);
14101423
}
14111424

14121425
nonnull_all
@@ -1603,7 +1616,7 @@ static int32_t parse_rrsig_rdata(
16031616
return code;
16041617
if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
16051618
return code;
1606-
if ((code = parse_algorithm_type(parser, type, &fields[1], rdata, token)) < 0)
1619+
if ((code = parse_algorithm(parser, type, &fields[1], rdata, token)) < 0)
16071620
return code;
16081621
if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
16091622
return code;
@@ -1710,7 +1723,7 @@ static int32_t parse_dnskey_rdata(
17101723
return code;
17111724
if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
17121725
return code;
1713-
if ((code = parse_algorithm_type(parser, type, &fields[2], rdata, token)) < 0)
1726+
if ((code = parse_algorithm(parser, type, &fields[2], rdata, token)) < 0)
17141727
return code;
17151728
take(parser, token);
17161729
if ((code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0)

src/generic/wks.h

+2-13
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ static really_inline uint8_t service_hash(uint64_t input, size_t length)
195195
}
196196

197197
nonnull((1,4))
198-
static really_inline bool scan_service(
198+
static really_inline int32_t scan_service(
199199
const char *data, size_t length, int32_t protocol, uint16_t *port)
200200
{
201201
uint8_t digit = (uint8_t)*data - '0';
@@ -242,18 +242,7 @@ static really_inline bool scan_service(
242242
(services[index].key.length == length);
243243
}
244244

245-
size_t count = 1;
246-
int32_t number = digit;
247-
248-
// FIXME: check for leading zero!
249-
if (length > 5) // port numbers must be between 0 and 65535
250-
return 0;
251-
for (; ((digit = ((uint8_t)data[count] - '0')) <= 9); count++)
252-
number = number * 10 + digit;
253-
if (count != length || number > 65535)
254-
return -1;
255-
*port = (uint16_t)number;
256-
return true;
245+
return scan_int16(data, length, port);
257246
}
258247

259248
#endif // WKS_H

src/haswell/parser.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#include "generic/apl.h"
3737
#include "generic/svcb.h"
3838
#include "generic/cert.h"
39-
#include "generic/dnssec.h"
39+
#include "generic/algorithm.h"
4040
#include "generic/types.h"
4141
#include "westmere/type.h"
4242
#include "generic/format.h"

src/westmere/bits.h

-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ static inline uint64_t leading_zeroes(uint64_t input_num) {
3434
}
3535

3636
static inline uint64_t prefix_xor(const uint64_t bitmask) {
37-
// There should be no such thing with a processor supporting avx2
38-
// but not clmul.
3937
__m128i all_ones = _mm_set1_epi8('\xFF');
4038
__m128i result = _mm_clmulepi64_si128(_mm_set_epi64x(0ULL, (long long)bitmask), all_ones, 0);
4139
return (uint64_t)_mm_cvtsi128_si64(result);

src/westmere/parser.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#include "generic/apl.h"
3737
#include "generic/svcb.h"
3838
#include "generic/cert.h"
39-
#include "generic/dnssec.h"
39+
#include "generic/algorithm.h"
4040
#include "generic/types.h"
4141
#include "westmere/type.h"
4242
#include "generic/format.h"

src/zone.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include <stdlib.h>
1616
#include <limits.h>
1717
#if _WIN32
18-
# include <Windows.h>
18+
# include <windows.h>
1919
# include <shlwapi.h>
2020
#endif
2121

0 commit comments

Comments
 (0)