Coverage Report

Created: 2023-06-07 06:23

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