Coverage Report

Created: 2026-07-30 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/fuzz/dns_message_parse.c
Line
Count
Source
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.9k
parse_message(isc_buffer_t *input, dns_message_t **messagep) {
47
21.9k
  isc_result_t result;
48
21.9k
  dns_message_t *message = NULL;
49
50
21.9k
  dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &message);
51
52
21.9k
  result = dns_message_parse(message, input, DNS_MESSAGEPARSE_BESTEFFORT);
53
21.9k
  if (result == DNS_R_RECOVERABLE) {
54
7.79k
    result = ISC_R_SUCCESS;
55
7.79k
  }
56
57
21.9k
  if (result == ISC_R_SUCCESS && messagep != NULL) {
58
17.4k
    *messagep = message;
59
17.4k
  } else {
60
4.49k
    dns_message_detach(&message);
61
4.49k
  }
62
63
21.9k
  return result;
64
21.9k
}
65
66
static isc_result_t
67
17.4k
print_message(dns_message_t *message) {
68
17.4k
  isc_result_t result;
69
17.4k
  isc_buffer_t buffer;
70
71
17.5k
  do {
72
17.5k
    isc_buffer_init(&buffer, output, output_len);
73
17.5k
    result = dns_message_totext(message, &dns_master_style_debug, 0,
74
17.5k
              &buffer);
75
17.5k
    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.5k
  } while (result == ISC_R_NOSPACE);
82
83
17.4k
  if (debug) {
84
0
    fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&buffer),
85
0
      output);
86
0
  }
87
88
17.4k
  return result;
89
17.4k
}
90
91
#define CHECKRESULT(r, f)                 \
92
44.0k
  {                                 \
93
44.0k
    r = (f);                  \
94
44.0k
    if (r != ISC_R_SUCCESS) { \
95
157
      goto cleanup;     \
96
157
    }                         \
97
44.0k
  }
98
99
static isc_result_t
100
8.82k
render_message(dns_message_t **messagep) {
101
8.82k
  isc_result_t result;
102
8.82k
  dns_message_t *message = *messagep;
103
8.82k
  isc_buffer_t buffer;
104
8.82k
  dns_compress_t cctx;
105
106
8.82k
  isc_buffer_init(&buffer, render_buf, sizeof(render_buf));
107
108
8.82k
  message->from_to_wire = DNS_MESSAGE_INTENTRENDER;
109
44.1k
  for (size_t i = 0; i < DNS_SECTION_MAX; i++) {
110
35.3k
    message->counts[i] = 0;
111
35.3k
  }
112
113
8.82k
  dns_compress_init(&cctx, mctx, 0);
114
115
8.82k
  CHECKRESULT(result, dns_message_renderbegin(message, &cctx, &buffer));
116
117
8.82k
  CHECKRESULT(result, dns_message_rendersection(message,
118
8.82k
                  DNS_SECTION_QUESTION, 0));
119
120
8.82k
  CHECKRESULT(result,
121
8.82k
        dns_message_rendersection(message, DNS_SECTION_ANSWER, 0));
122
8.81k
  CHECKRESULT(result, dns_message_rendersection(
123
8.81k
            message, DNS_SECTION_AUTHORITY, 0));
124
125
8.73k
  CHECKRESULT(result, dns_message_rendersection(
126
8.73k
            message, DNS_SECTION_ADDITIONAL, 0));
127
128
8.67k
  dns_message_renderend(message);
129
130
8.67k
  dns_compress_invalidate(&cctx);
131
132
8.67k
  message->from_to_wire = DNS_MESSAGE_INTENTPARSE;
133
134
8.67k
  dns_message_detach(messagep);
135
136
8.67k
  result = parse_message(&buffer, messagep);
137
138
8.67k
  return result;
139
140
157
cleanup:
141
157
  dns_compress_invalidate(&cctx);
142
157
  return result;
143
8.73k
}
144
145
int
146
13.3k
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
147
13.3k
  isc_buffer_t buffer;
148
13.3k
  isc_result_t result;
149
13.3k
  dns_message_t *message = NULL;
150
151
13.3k
  if (size > 65535) {
152
1
    return 0;
153
1
  }
154
155
13.3k
  isc_buffer_constinit(&buffer, data, size);
156
13.3k
  isc_buffer_add(&buffer, size);
157
13.3k
  isc_buffer_setactive(&buffer, size);
158
159
13.3k
  CHECK(parse_message(&buffer, &message));
160
161
8.82k
  CHECK(print_message(message));
162
163
8.82k
  CHECK(render_message(&message));
164
165
8.66k
  CHECK(print_message(message));
166
167
13.3k
cleanup:
168
13.3k
  if (message != NULL) {
169
8.81k
    dns_message_detach(&message);
170
8.81k
  }
171
172
13.3k
  return 0;
173
8.66k
}