Coverage Report

Created: 2026-05-16 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qpid-proton/c/tests/fuzz/fuzz-connection-driver.c
Line
Count
Source
1
/*
2
 *
3
 * Licensed to the Apache Software Foundation (ASF) under one
4
 * or more contributor license agreements.  See the NOTICE file
5
 * distributed with this work for additional information
6
 * regarding copyright ownership.  The ASF licenses this file
7
 * to you under the Apache License, Version 2.0 (the
8
 * "License"); you may not use this file except in compliance
9
 * with the License.  You may obtain a copy of the License at
10
 *
11
 *   http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing,
14
 * software distributed under the License is distributed on an
15
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
 * KIND, either express or implied.  See the License for the
17
 * specific language governing permissions and limitations
18
 * under the License.
19
 *
20
 */
21
22
#include <stdint.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include "proton/connection_driver.h"
28
#include "proton/engine.h"
29
#include "proton/logger.h"
30
#include "proton/message.h"
31
#include "proton/object.h"
32
33
#include "libFuzzingEngine.h"
34
35
// This fuzzer is a variant of the receive.c proactor example
36
37
529k
#define MAX_SIZE 1024
38
39
typedef char str[MAX_SIZE];
40
41
typedef struct app_data_t {
42
  str container_id;
43
  pn_rwbytes_t message_buffer;
44
  int message_count;
45
  int received;
46
} app_data_t;
47
48
static void fdc_write(pn_connection_driver_t *driver);
49
size_t fcd_read(pn_connection_driver_t *driver, uint8_t **data, size_t *size);
50
static void decode_message(pn_delivery_t *dlv);
51
static void handle(app_data_t *app, pn_event_t *event);
52
static void check_condition(pn_event_t *e, pn_condition_t *cond);
53
54
// const bool VERBOSE = true;
55
const bool VERBOSE = false;
56
// const bool ERRORS = true;
57
const bool ERRORS = false;
58
59
// I could not get rid of the error messages on stderr in any other way
60
430
void devnull(intptr_t context, pn_log_subsystem_t sub,  pn_log_level_t sev, const char *message) {}
61
62
26.8k
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
63
26.8k
  if (VERBOSE)
64
0
    printf("BEGIN LLVMFuzzerTestOneInput\n");
65
26.8k
  app_data_t app = {{0}};
66
26.8k
  sprintf(app.container_id, "%s:%06x",
67
26.8k
           "fuzz_connection_driver", rand() & 0xffffff);
68
69
26.8k
  pn_connection_driver_t driver;
70
26.8k
  if (pn_connection_driver_init(&driver, NULL, NULL) != 0) {
71
0
    printf("pn_connection_driver_init\n");
72
0
    exit(1);
73
0
  }
74
75
26.8k
  pn_logger_set_log_sink(pn_default_logger(), devnull, 0);
76
77
26.8k
  uint8_t *data = (uint8_t *)Data;
78
26.8k
  size_t size = Size;
79
80
26.8k
  fdc_write(&driver);
81
82
26.8k
  pn_event_t *event;
83
215k
  while ((event = pn_connection_driver_next_event(&driver)) != NULL) {
84
188k
    handle(&app, event);
85
188k
  }
86
87
26.8k
  fdc_write(&driver);
88
89
34.3k
  do {
90
34.3k
    fdc_write(&driver);
91
34.3k
    fcd_read(&driver, &data, &size);
92
34.3k
    if (VERBOSE)
93
0
      printf("size is %d, data is %p\n", (int)size, (void *)data);
94
11.8M
    while ((event = pn_connection_driver_next_event(&driver)) != NULL) {
95
11.7M
      handle(&app, event);
96
11.7M
    }
97
34.3k
  } while (size > 0);
98
99
26.8k
  pn_connection_driver_close(&driver);
100
26.8k
  pn_connection_driver_destroy(&driver);
101
26.8k
  if (VERBOSE)
102
0
    printf("END LLVMFuzzerTestOneInput\n");
103
26.8k
  return 0;
104
26.8k
}
105
106
11.9M
static void handle(app_data_t *app, pn_event_t *event) {
107
11.9M
  switch (pn_event_type(event)) {
108
109
26.8k
  case PN_CONNECTION_INIT: {
110
26.8k
    pn_connection_t *c = pn_event_connection(event);
111
26.8k
    pn_connection_set_container(c, app->container_id);
112
26.8k
    pn_connection_open(c);
113
26.8k
    pn_session_t *s = pn_session(c);
114
26.8k
    pn_session_open(s);
115
26.8k
    pn_link_t *l = pn_receiver(s, "my_receiver");
116
26.8k
    pn_terminus_set_address(pn_link_source(l), NULL);
117
26.8k
    pn_link_open(l);
118
26.8k
    pn_link_flow(l, 20);
119
26.8k
  } break;
120
121
9.17M
  case PN_DELIVERY: {
122
    /* A message has been received */
123
9.17M
    pn_link_t *link = NULL;
124
9.17M
    pn_delivery_t *dlv = pn_event_delivery(event);
125
9.17M
    if (pn_delivery_readable(dlv) && !pn_delivery_partial(dlv)) {
126
265k
      link = pn_delivery_link(dlv);
127
265k
      decode_message(dlv);
128
      /* Accept the delivery */
129
265k
      pn_delivery_update(dlv, PN_ACCEPTED);
130
      /* done with the delivery, move to the next and free it */
131
265k
      pn_link_advance(link);
132
265k
      pn_delivery_settle(dlv); /* dlv is now freed */
133
265k
    }
134
9.17M
  } break;
135
136
8.52k
  case PN_TRANSPORT_ERROR:
137
8.52k
    check_condition(event, pn_transport_condition(pn_event_transport(event)));
138
8.52k
    pn_connection_close(pn_event_connection(event));
139
8.52k
    break;
140
141
1.02k
  case PN_CONNECTION_REMOTE_CLOSE:
142
1.02k
    check_condition(event,
143
1.02k
                    pn_connection_remote_condition(pn_event_connection(event)));
144
1.02k
    pn_connection_close(pn_event_connection(event));
145
1.02k
    break;
146
147
2.13k
  case PN_SESSION_REMOTE_CLOSE:
148
2.13k
    check_condition(event,
149
2.13k
                    pn_session_remote_condition(pn_event_session(event)));
150
2.13k
    pn_connection_close(pn_event_connection(event));
151
2.13k
    break;
152
153
14.3k
  case PN_LINK_REMOTE_CLOSE:
154
22.8k
  case PN_LINK_REMOTE_DETACH:
155
22.8k
    check_condition(event, pn_link_remote_condition(pn_event_link(event)));
156
22.8k
    pn_connection_close(pn_event_connection(event));
157
22.8k
    break;
158
159
2.74M
  default:
160
2.74M
    break;
161
11.9M
  }
162
11.9M
}
163
164
34.5k
static void check_condition(pn_event_t *e, pn_condition_t *cond) {
165
34.5k
  if (VERBOSE)
166
0
    printf("beginning check_condition\n");
167
34.5k
  if (pn_condition_is_set(cond)) {
168
8.56k
    if (VERBOSE || ERRORS)
169
0
      fprintf(stderr, "%s: %s: %s\n", pn_event_type_name(pn_event_type(e)),
170
0
              pn_condition_get_name(cond), pn_condition_get_description(cond));
171
8.56k
  }
172
34.5k
}
173
174
265k
static void decode_message(pn_delivery_t *dlv) {
175
265k
  static char buffer[MAX_SIZE];
176
265k
  ssize_t len;
177
  // try to decode the message body
178
265k
  if (pn_delivery_pending(dlv) < MAX_SIZE) {
179
    // read in the raw data
180
263k
    len = pn_link_recv(pn_delivery_link(dlv), buffer, MAX_SIZE);
181
263k
    if (len > 0) {
182
      // decode it into a proton message
183
134k
      pn_message_t *m = pn_message();
184
134k
      if (PN_OK == pn_message_decode(m, buffer, len)) {
185
134k
        char *s = pn_tostring(pn_message_body(m));
186
134k
        if (ERRORS)
187
0
          printf("%s\n", s);
188
134k
        free(s);
189
134k
      }
190
134k
      pn_message_free(m);
191
134k
    }
192
263k
  }
193
265k
}
194
195
// reads up to `size` bytes from `data`,
196
// updates `data` pointer and `size` to the unread portion of original `data`,
197
// returns new value of `size`
198
34.3k
size_t fcd_read(pn_connection_driver_t *driver, uint8_t **data, size_t *size) {
199
34.3k
  pn_rwbytes_t buf = pn_connection_driver_read_buffer(driver);
200
34.3k
  size_t s = (*size < buf.size) ? *size : buf.size;
201
34.3k
  if (buf.start == NULL) {
202
    // The engine offered a null buffer for further input.
203
    // This is legit, because it is just that the "socket" was closed
204
    //  for further input, after reading the invalid header.
205
283
    *size = 0;
206
283
    return *size;
207
283
  }
208
34.0k
  memcpy(buf.start, *data, s);
209
210
34.0k
  pn_connection_driver_read_done(driver, s);
211
34.0k
  *data += s;
212
34.0k
  *size -= s;
213
214
34.0k
  return *size;
215
34.3k
}
216
217
// drops the data in the buffer and reports them as written
218
88.1k
static void fdc_write(pn_connection_driver_t *driver) {
219
88.1k
  pn_bytes_t buffer = pn_connection_driver_write_buffer(driver);
220
88.1k
  pn_connection_driver_write_done(driver, buffer.size);
221
88.1k
}