Coverage Report

Created: 2026-10-28 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/librabbitmq/fuzz/fuzz_read_message.c
Line
Count
Source
1
// Copyright 2007 - 2026, Alan Antonuk and the rabbitmq-c contributors.
2
// SPDX-License-Identifier: mit
3
4
#include <stdint.h>
5
#include <stdlib.h>
6
#include <string.h>
7
8
#include <rabbitmq-c/amqp.h>
9
#include <rabbitmq-c/framing.h>
10
11
#include "amqp_socket.h"
12
13
11.0k
#define MAX_INPUT_SIZE (1U << 20)
14
204k
#define MAX_BODY_SIZE (1U << 20)
15
16
struct fuzz_socket_t {
17
  const struct amqp_socket_class_t *klass;
18
  const uint8_t *data;
19
  size_t size;
20
  size_t offset;
21
};
22
23
static ssize_t fuzz_socket_send(AMQP_UNUSED void *base,
24
                                AMQP_UNUSED const void *buf, size_t len,
25
0
                                AMQP_UNUSED int flags) {
26
0
  return (ssize_t)len;
27
0
}
28
29
static ssize_t fuzz_socket_recv(void *base, void *buf, size_t len,
30
7.65k
                                AMQP_UNUSED int flags) {
31
7.65k
  struct fuzz_socket_t *socket = (struct fuzz_socket_t *)base;
32
7.65k
  size_t remaining = socket->size - socket->offset;
33
7.65k
  size_t count;
34
35
7.65k
  if (remaining == 0) {
36
2.10k
    return AMQP_STATUS_CONNECTION_CLOSED;
37
2.10k
  }
38
39
5.54k
  count = remaining < len ? remaining : len;
40
5.54k
  memcpy(buf, socket->data + socket->offset, count);
41
5.54k
  socket->offset += count;
42
5.54k
  return (ssize_t)count;
43
7.65k
}
44
45
static int fuzz_socket_open(AMQP_UNUSED void *base,
46
                            AMQP_UNUSED const char *host,
47
                            AMQP_UNUSED int port,
48
0
                            AMQP_UNUSED const struct timeval *timeout) {
49
0
  return AMQP_STATUS_OK;
50
0
}
51
52
static int fuzz_socket_close(AMQP_UNUSED void *base,
53
0
                             AMQP_UNUSED amqp_socket_close_enum force) {
54
0
  return AMQP_STATUS_OK;
55
0
}
56
57
2.10k
static int fuzz_socket_get_sockfd(AMQP_UNUSED void *base) { return 0; }
58
59
5.47k
static void fuzz_socket_delete(void *base) { free(base); }
60
61
static const struct amqp_socket_class_t fuzz_socket_class = {
62
    fuzz_socket_send, fuzz_socket_recv,       fuzz_socket_open,
63
    fuzz_socket_close, fuzz_socket_get_sockfd, fuzz_socket_delete};
64
65
204k
static uint64_t read_be64(const uint8_t *data) {
66
204k
  uint64_t value = 0;
67
204k
  size_t i;
68
69
1.84M
  for (i = 0; i < 8; i++) {
70
1.63M
    value = (value << 8) | data[i];
71
1.63M
  }
72
204k
  return value;
73
204k
}
74
75
5.53k
static int body_sizes_are_bounded(const uint8_t *data, size_t size) {
76
5.53k
  size_t offset = 0;
77
78
5.53k
  if (size >= 8 && memcmp(data, "AMQP", 4) == 0) {
79
103
    offset = 8;
80
103
  }
81
82
337k
  while (size - offset >= 8) {
83
332k
    uint32_t payload_size = ((uint32_t)data[offset + 3] << 24) |
84
332k
                            ((uint32_t)data[offset + 4] << 16) |
85
332k
                            ((uint32_t)data[offset + 5] << 8) |
86
332k
                            (uint32_t)data[offset + 6];
87
332k
    size_t frame_size = (size_t)payload_size + 8;
88
89
332k
    if (frame_size > size - offset) {
90
327
      break;
91
327
    }
92
331k
    if (data[offset] == AMQP_FRAME_HEADER && payload_size >= 12 &&
93
204k
        read_be64(data + offset + 11) > MAX_BODY_SIZE) {
94
67
      return 0;
95
67
    }
96
331k
    offset += frame_size;
97
331k
  }
98
99
5.47k
  return 1;
100
5.53k
}
101
102
5.53k
extern int LLVMFuzzerTestOneInput(const char *data, size_t size) {
103
5.53k
  amqp_connection_state_t connection;
104
5.53k
  amqp_message_t message;
105
5.53k
  struct fuzz_socket_t *socket;
106
5.53k
  amqp_rpc_reply_t reply;
107
108
5.53k
  if (size == 0 || size > MAX_INPUT_SIZE ||
109
5.53k
      !body_sizes_are_bounded((const uint8_t *)data, size)) {
110
67
    return 0;
111
67
  }
112
113
5.47k
  connection = amqp_new_connection();
114
5.47k
  if (connection == NULL) {
115
0
    return 0;
116
0
  }
117
118
5.47k
  socket = (struct fuzz_socket_t *)calloc(1, sizeof(*socket));
119
5.47k
  if (socket == NULL) {
120
0
    amqp_destroy_connection(connection);
121
0
    return 0;
122
0
  }
123
124
5.47k
  socket->klass = &fuzz_socket_class;
125
5.47k
  socket->data = (const uint8_t *)data;
126
5.47k
  socket->size = size;
127
5.47k
  amqp_set_socket(connection, (amqp_socket_t *)socket);
128
129
5.47k
  reply = amqp_read_message(connection, 1, &message, 0);
130
5.47k
  if (reply.reply_type == AMQP_RESPONSE_NORMAL) {
131
15
    amqp_destroy_message(&message);
132
15
  }
133
134
5.47k
  amqp_destroy_connection(connection);
135
5.47k
  return 0;
136
5.47k
}