Coverage Report

Created: 2025-08-03 06:33

/src/bind9/fuzz/dns_message_parse.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
5
 *
6
 * This Source Code Form is subject to the terms of the Mozilla Public
7
 * License, v. 2.0. If a copy of the MPL was not distributed with this
8
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9
 *
10
 * See the COPYRIGHT file distributed with this work for additional
11
 * information regarding copyright ownership.
12
 */
13
14
#include <inttypes.h>
15
#include <stdbool.h>
16
#include <stdlib.h>
17
18
#include <isc/buffer.h>
19
#include <isc/commandline.h>
20
#include <isc/file.h>
21
#include <isc/mem.h>
22
#include <isc/result.h>
23
#include <isc/string.h>
24
#include <isc/util.h>
25
26
#include <dns/message.h>
27
28
#include "fuzz.h"
29
30
bool debug = false;
31
32
static isc_mem_t *mctx = NULL;
33
static uint8_t *output = NULL;
34
static size_t output_len = 1024;
35
static uint8_t render_buf[64 * 1024 - 1];
36
37
int
38
18
LLVMFuzzerInitialize(int *argc ISC_ATTR_UNUSED, char ***argv ISC_ATTR_UNUSED) {
39
18
  isc_mem_create("fuzz", &mctx);
40
18
  output = isc_mem_get(mctx, output_len);
41
42
18
  return 0;
43
18
}
44
45
static isc_result_t
46
21.1k
parse_message(isc_buffer_t *input, dns_message_t **messagep) {
47
21.1k
  isc_result_t result;
48
21.1k
  dns_message_t *message = NULL;
49
50
21.1k
  dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &message);
51
52
21.1k
  result = dns_message_parse(message, input, DNS_MESSAGEPARSE_BESTEFFORT);
53
21.1k
  if (result == DNS_R_RECOVERABLE) {
54
7.83k
    result = ISC_R_SUCCESS;
55
7.83k
  }
56
57
21.1k
  if (result == ISC_R_SUCCESS && messagep != NULL) {
58
17.1k
    *messagep = message;
59
17.1k
  } else {
60
4.02k
    dns_message_detach(&message);
61
4.02k
  }
62
63
21.1k
  return result;
64
21.1k
}
65
66
static isc_result_t
67
17.1k
print_message(dns_message_t *message) {
68
17.1k
  isc_result_t result;
69
17.1k
  isc_buffer_t buffer;
70
71
17.1k
  do {
72
17.1k
    isc_buffer_init(&buffer, output, output_len);
73
17.1k
    result = dns_message_totext(message, &dns_master_style_debug, 0,
74
17.1k
              &buffer);
75
17.1k
    if (result == ISC_R_NOSPACE) {
76
14
      isc_mem_put(mctx, output, output_len);
77
14
      output_len *= 2;
78
14
      output = isc_mem_get(mctx, output_len);
79
14
      continue;
80
14
    }
81
17.1k
  } while (result == ISC_R_NOSPACE);
82
83
17.1k
  if (debug) {
84
0
    fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&buffer),
85
0
      output);
86
0
  }
87
88
17.1k
  return result;
89
17.1k
}
90
91
#define CHECKRESULT(r, f)                 \
92
43.4k
  {                                 \
93
43.4k
    r = (f);                  \
94
43.4k
    if (r != ISC_R_SUCCESS) { \
95
202
      goto cleanup;     \
96
202
    }                         \
97
43.4k
  }
98
99
static isc_result_t
100
8.71k
render_message(dns_message_t **messagep) {
101
8.71k
  isc_result_t result;
102
8.71k
  dns_message_t *message = *messagep;
103
8.71k
  isc_buffer_t buffer;
104
8.71k
  dns_compress_t cctx;
105
106
8.71k
  isc_buffer_init(&buffer, render_buf, sizeof(render_buf));
107
108
8.71k
  message->from_to_wire = DNS_MESSAGE_INTENTRENDER;
109
43.5k
  for (size_t i = 0; i < DNS_SECTION_MAX; i++) {
110
34.8k
    message->counts[i] = 0;
111
34.8k
  }
112
113
8.71k
  dns_compress_init(&cctx, mctx, 0);
114
115
8.71k
  CHECKRESULT(result, dns_message_renderbegin(message, &cctx, &buffer));
116
117
8.71k
  CHECKRESULT(result, dns_message_rendersection(message,
118
8.71k
                  DNS_SECTION_QUESTION, 0));
119
120
8.70k
  CHECKRESULT(result,
121
8.70k
        dns_message_rendersection(message, DNS_SECTION_ANSWER, 0));
122
8.66k
  CHECKRESULT(result, dns_message_rendersection(
123
8.66k
            message, DNS_SECTION_AUTHORITY, 0));
124
125
8.62k
  CHECKRESULT(result, dns_message_rendersection(
126
8.62k
            message, DNS_SECTION_ADDITIONAL, 0));
127
128
8.51k
  dns_message_renderend(message);
129
130
8.51k
  dns_compress_invalidate(&cctx);
131
132
8.51k
  message->from_to_wire = DNS_MESSAGE_INTENTPARSE;
133
134
8.51k
  dns_message_detach(messagep);
135
136
8.51k
  result = parse_message(&buffer, messagep);
137
138
8.51k
  return result;
139
140
202
cleanup:
141
202
  dns_compress_invalidate(&cctx);
142
202
  return result;
143
8.62k
}
144
145
int
146
12.6k
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
147
12.6k
  isc_buffer_t buffer;
148
12.6k
  isc_result_t result;
149
12.6k
  dns_message_t *message = NULL;
150
151
12.6k
  if (size > 65535) {
152
4
    return 0;
153
4
  }
154
155
12.6k
  isc_buffer_constinit(&buffer, data, size);
156
12.6k
  isc_buffer_add(&buffer, size);
157
12.6k
  isc_buffer_setactive(&buffer, size);
158
159
12.6k
  result = parse_message(&buffer, &message);
160
12.6k
  if (result != ISC_R_SUCCESS) {
161
3.94k
    goto cleanup;
162
3.94k
  }
163
164
8.71k
  result = print_message(message);
165
8.71k
  if (result != ISC_R_SUCCESS) {
166
0
    goto cleanup;
167
0
  }
168
169
8.71k
  result = render_message(&message);
170
8.71k
  if (result != ISC_R_SUCCESS) {
171
282
    goto cleanup;
172
282
  }
173
174
8.43k
  result = print_message(message);
175
8.43k
  if (result != ISC_R_SUCCESS) {
176
0
    goto cleanup;
177
0
  }
178
179
12.6k
cleanup:
180
12.6k
  if (message != NULL) {
181
8.63k
    dns_message_detach(&message);
182
8.63k
  }
183
184
12.6k
  return 0;
185
8.43k
}