Coverage Report

Created: 2026-09-14 06:46

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